LINUX.ORG.RU

Нелогичная логика

 


0

2

Куприв!

Пишу я тут очередной ляс и в процессе компиляции компилятор и даже линковщик(!) выдаёт мне такие предупреждения:

cc -Wall -O2   -c -o sim7600-at.o sim7600-at.c
sim7600-at.c: In function 'simApplicationToolkit':
sim7600-at.c:1013:17: warning: implicit declaration of function 'gets'; did you mean 'fgets'? [-Wimplicit-function-declaration]
 1013 |                 gets( userAns );
      |                 ^~~~
      |                 fgets
cc -s  sim7600-at.o utils_pdu_sms.o   -o sim7600-at
/usr/bin/ld: sim7600-at.o: in function `simApplicationToolkit':
sim7600-at.c:(.text+0xf91): warning: the `gets' function is dangerous and should not be used.

Справедливо, но тогда почему нет подобного предупреждения при использовани strncpy, например, которая тоже дырявая, даже не смотря на n?

★★
Ответ на: комментарий от u5er

что он как минимум по теме пишет

он берет длину строки перед ее копированием. это избыточно. я б ему блевик поставил, но это будет горе матери и позор отца. потому не ставлю.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Я полагаю, что это абстрактный пример. В реальном коде фактическая длина строки может быть уже заранее получена тем или иным путём.

u5er ★★
() автор топика
Ответ на: комментарий от u5er

ожидается

строка будет читаться

Ожидаться и читаться может кодом и программистом, который его писал. Поэтому повторю - всё зависит от того, что ты накодил. Если твой код для нуль-терминированных строк - просто не давай ему на вход результат strncpy. Но таким кодом мир не ограничивается, в ряде случаев используются другие способы определения длины.

firkax ★★★★★
()
Ответ на: комментарий от vbr

strcpy с проверкой в стандартной библиотеке нет. strlcpy это из BSD и в стандартном C такой функции нет. Если нужно такое поведение - значит либо пишешь такую функцию сам, либо подключаешь libbsd.

Смотря в чьей стандартной библиотеке. В bsd libc давным давно есть, например, в string.h. Да и вообще, он есть практически везде, glibc одно из редких исключений (а так же там же msvcrt): https://www.sourceware.org/glibc/wiki/strlcpy

firkax ★★★★★
()
Ответ на: комментарий от alysnix

Сишный стандарт, по неизвестной мне причине, до сих пор разрешает вызывать функции без объявления. Если функция не объявлена, то считается что все аргументы у неё int и возвращает она тоже int, ЕМНИП.

Угадай как код полагающийся на это ломается на LP64, например.

a1ba ★★
()
Последнее исправление: a1ba (всего исправлений: 1)
Ответ на: комментарий от anonymous

GCC и Clang понимают семантику

разве из-за того, что компилятор якобы умный, имеет смысл писать неидеальные алгоритмы? алгоритм это семантика, сама по себе, вне наличия и качества компилятора.

alysnix ★★★
()
Ответ на: комментарий от firkax

ноль-терминированные строки это библиотечная абстракция

это способ представления текстовых строк еще от эпохи ассемблеров. откуда оно и перекочевало в си. а не какая-то там «абстракция».

alysnix ★★★
()
Ответ на: комментарий от firkax

Нет там никакого UB

https://en.cppreference.com/w/c/string/byte/strlen

The behavior is undefined if str is not a pointer to a null-terminated byte string.


ноль-терминированные строки это библиотечная абстракция …, а не требование языка.

string.h - входит в стандарт языка и это стандартная библиотека языка.

anonymous
()
Ответ на: комментарий от anonymous

Алгоритмы надо писать корректные, удовлетворяющие условиям. В условиях есть требование не использовать strlen?

мельчите, алгоритмы должны быть минимальной вычислительной сложности, при соблюдении требований к их функциональности.

фактически время работы приведеннного куска кода увеличивается вдвое, просто потому, что там избыточные операции

alysnix ★★★
()
Ответ на: комментарий от alysnix

алгоритмы должны быть минимальной вычислительной сложности

Это огромный-огромный словарь на много-много параметров, который сразу [O(1)] возвращает результат по входным параметрам.

anonymous
()
Ответ на: комментарий от anonymous

какой еще словарь? вот код, что фиркакс написал в целях познавательных. а я сказал, что длина не нужна и всю логику надо привести к более стройной. и усьо!

len = strlen(src);
if(len>=buflen) { fprintf(stderr,"string overflow!\n"); abort(); }
bcopy(src, buf, len);
buf[len] = 0;
alysnix ★★★
()
Ответ на: комментарий от alysnix

У вас просто разный набор «стандартных» функций, которые «разрешено» использовать в алгоритме. Разный базис - разные коэфициенты вектора (одного и того же). Но результат (должен быть) один.

anonymous
()
Ответ на: комментарий от anonymous

У вас просто разный набор «стандартных» функций, которые «разрешено» использовать в алгоритме.

так не бывает. алгоритм первичен, набор стандартный - вторичен. если он не устраивает - делай свой набор. стандартные функции это просто множество неких удобных абстракции и функций, который выбрали голосованием, и к которому вас никто гвоздями не прибил.

да там вроде и на стандартных функциях можно делать корректно и без длины. лень хелпы смотреть

alysnix ★★★
()
Ответ на: комментарий от alysnix

алгоритм первичен

Нет. Как минимум алгоритмы можно реализовать на машине Тьюринга или как лямбда-исчисление. Это разные алгоритмы, с разным пониманием вычислительной сложности. Не говоря о разных алгоритмах в зависимости от сложности базовых/элементарных операций, например, какая-нибудь «квантовая машина» считает интегралы быстрее, чем ужножает/делит.

anonymous
()
Ответ на: комментарий от anonymous

Нет. Как минимум алгоритмы можно реализовать на машине Тьюринга или как лямбда-исчисление.

какая разница на чем ты будешь перебирать массив, если это не нужно. на машине тюринга или лямбда-исчислением. ты будешь заниматься лишними операциями просто потому, что так написано в неправильном императивном алгоритме. а в правильном - этого не будет.

alysnix ★★★
()
Ответ на: комментарий от vbr

Например в этом коде использовать что-либо кроме strcpy не уместно:

vbr - я тебя понимаю, но ведь в реальном коТе в 99.9% будет:

strcpy(buf, stroka_ot_usera_Vasi_ya_emu_doveryau_pili_kakto_vmeste);

И тебя поимеют :)

Спор ни о чём, об этом спорят столько, сколько Си существует.

Я лично считаю что самая главная характеристика Си - это то, что он «высокоуровневый ассемблер»(C)… Писать приложухи на нём не надо, только ту часть в них где происходит лютый байтодроЧЪ (кодек к примеру), либо драйверы какие, либо кишки ОС\FS … потому как «настоящий» ЯП там только мешает :)

Но в ойТи принято есть суп вилкой, это наше всЁ :)

anonymous
()
Ответ на: комментарий от vbr

Нужен безопасный язык - берите Rust. Или Go. Или Python.

  • Java, JS\TS, Swift

Да хоть Ocaml! - там наконец то ну гру-гря то, что в питоне называют GIL - похерили и он теперь сЪест все ваши корки :)

Полно ведь ЯП-шек, на все вкусы и стли - по паре … нет ЯЪ! - берут сишку и лепят очередной «склад\магазин» … Зойчем?!?!? :(

anonymous
()
Ответ на: комментарий от u5er

Спасибо, но я возьму аду при необходимости.

James Bond-ы докладывают что она только на Бериеве (да у то где то в уголочке) осталась :( Но таки да:

  • Ada
anonymous
()
Ответ на: комментарий от u5er

Зойчем?! Зашкафом! Потому что желание совпадает с возможностями! =P

От-тожЪ(C) :)

PS: Чтобы потушить пожар залив его … бензином ;-D - предлагаю вам ещё тему «Корректная и эффективная обработка UTF (UTF-8) строк в языке Си» …

PPS: Вот я сволочь 8-)

anonymous
()
Ответ на: комментарий от anonymous

Корректная и эффективная обработка UTF (UTF-8) строк в языке Си

Поздно: я уже занимаюсь этим в контексте написания своей операционки =P Не уверен, что получается корректно и эффективно, но лыжи едут.

u5er ★★
() автор топика
Ответ на: комментарий от anonymous

Корректная и эффективная обработка UTF (UTF-8) строк в языке Си» …

Корректная обработка их весьма простая, а вот насчёт эффективной - это невозможно, и язык тут ни при чём. Виноват сам utf-8, что в нём для вычисления индекса символа надо сканировать всю строку до него. Это на любом языке будет уродливый оверхед (хотя на некоторых он может быть и спрятан от кодера внутрь библиотеки, но он от этого не исчезает).

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

для вычисления индекса символа надо сканировать всю строку до него.

Если оптимизировать по скорости, то можно использовать uint32_t для хранения каждого символа, тогда доступ будет быстрым.

u5er ★★
() автор топика
Ответ на: комментарий от u5er

Си это язык, на котором пишут программы, а POSIX (один из его разделов) - стандарт на апи между ОС (включая libc) и программами. То есть именно это стандарт на системную библиотеку.

firkax ★★★★★
()
Ответ на: комментарий от u5er

Хранить так конечно можно, только это будет уже не utf-8. utf-8 это именно неудобная для софта кодировка с переменной длиной символа. Хотя у неё и есть другие плюсы, ради которых с ней мирятся.

firkax ★★★★★
()
Ответ на: комментарий от firkax

POSIX это и есть сишный стандарт

это стандарт на системную библиотеку

«Эволюция» стандарта за несколько часов.

Тем временем POSIX-2024 поддерживат только C17, хотя уже вышел С23.

anonymous
()
Ответ на: комментарий от iron

Перефразирую: чем bcopy не устраивает?

Вообще, на самом деле причины (заранее согласен что ни одна из них не критическая) предпочитать bcopy есть:

1) он занимает на 1 символ меньше чем memcpy и на 2 символа меньше чем memmove (и кстати он аналог второго а не первого)

2) memcpy нету в 4.2BSD, а bcopy - есть

3) memcpy замешан в скандале с некими умниками, испортившими его исторически принятое поведение (копирование строго снизу вверх), и что самое плохое - эту регрессию так и не откатили

4) используя набор bcopy/bcmp/bzero вместо соответствующих memXXX, мы экономим не только символы в названиях функций, но и лишний аргумент у memset (кстати была история, когда из-за бага memset всегда заполнял память нулями и игнорил второй аругмент - и вроде бы это никто так и не заметил на практике).

firkax ★★★★★
()
Ответ на: комментарий от firkax
  1. он занимает на 1 символ меньше чем memcpy и на 2 символа меньше чем memmove (и кстати он аналог второго а не первого)

При оптимизации -O2 результирующему коду пофигу сколько там символов в названии функций.

  1. memcpy нету в 4.2BSD, а bcopy - есть

Ок, но при написании новый программы, какова вероятность что ее будут запускать на системе до 4.2BSD? Подозреваю, что околонулевая. К тому, же это уже легаси:

     IEEE Std 1003.1-2008 (“POSIX.1”) removes the specification of bcopy() and
     it is marked as LEGACY in IEEE Std 1003.1-2004 (“POSIX.1”).  New programs
     should use memmove(3).  If the input and output buffer do not overlap,
     then memcpy(3) is more efficient.

К тому же, memcpy() и собратья в FreeBSD имеют оптимизации с использованием SIMD инструкций для ускорения копирования блоков памяти, в отличие от bcopy().

iron ★★★★★
()
Ответ на: комментарий от iron

1. Причём тут результирующий код? Он и без оптимизаций вообще от названий функций не зависит. Речь про то что надо на 1 кнопку меньше нажимать когда пишешь код.

2. Ну я сразу сказал что причины эти некритичные.

Насчёт «легаси» и ссылок на всякие стандарты - это всё ерунда. Никто bcopy удалять не собирается и никогда не удалит.

Насчёт оптимизаций: вот общий исходник для bcopy, memcpy и memmove - отличия только в ifdef-ах, вот ссылка на него для memcpy и для memmove.

Для amd64 действительно есть оптимизированная реализация. Вот она: bcopy memcpy memmove. Опять та же история с общим исходником и алиасами к нему.

Где simd я не нашёл, но если он там где-то есть то очевидно по той же схеме.

Так что это всё одно и то же сейчас, разница реально только в количестве букв для набора на клавиатуре.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Никто bcopy удалять не собирается и никогда не удалит.

Надо спросить у оффтопщиков (win msvc, macos), есть ли у них в стандартной libc bcopy и тп.

https://godbolt.org при выборе msvc ругается на отсутствие bcopy. Значит, кто-то удалил.

anonymous
()
Ответ на: комментарий от anonymous

У них его и не было. Ладно, признаю что использование bcopy может нарушить совместимость с оффтопиком. В любом случае, для смысла примера это несущественно (как и место подсчёта длины строки, к которому кто-то придрался).

firkax ★★★★★
()