fk0, легенда (24.05.2013 00:40, просмотров: 489) ответил Evgeny_CD на NASA C STYLE GUIDE.
Через-чур. По пунктам с чем не согласен: > 1 Do not stray outside the language definition.
Считаю, _иногда_, GNU расширения стоят того, чтоб их использовать. В частности ({expr}), typeof(var), struct xxx = { .field=value, .field=value }.
> 4 Do not use direct or indirect recursion.
Во многих алгоритмах сложно отказаться от рекурсии. Попытка отказа ведёт к достаточно дикими решениям, ничем не лучше рекурсии, зачастую. Помимо собственно рекурсии не нужно забывать об автоматических переменных. Без рекурсии нужен тот же malloc, например, против которого они тоже против.
> 5 Do not use dynamic memory allocation after task initialization.
Тогда памяти нужно в несколько раз больше: сразу и на всё. А не на первое-второе-третье поочерёдно.
> 11 Do not use goto, setjmp or longjmp.
Классика жанра -- два вложенных цикла. Как, спрашивается, быть, если нужен break из обоих? А у setjmp и longjmp может быть плохонькая замена исключениям в C++. Хотя с риском не высвободить чего-либо и т.п. Но это может быть лучше, в ряде случаев, чем дичайший говнокод с передачей ошибок через 10 слоёв функций.
> 14 Check the return value of non-void functions, or explicitly cast to (void).
Ибо ошибки возвращаются вперемешку с возвращаемыми значениям. Нет исключений. Но практически это порядочный маразм. Так и printf не написать.
> *17 Use U32, I16, etc instead of predefined C data types such as int, short, etc.
Говнокодище! Звучит так. Мол мы не можем гарантировать работу наших программ с переменной длины int, и тестировать не можем. Поэтому сделаем свой int фиксированного размера. Со всем вытекающим негативом от нестандартных типов. Начиная от того, что непонятно какой у него формат в printf("%что?", (U32)x), scanf тоже. Или отсутствие констант означающих минимальные/максимальные размерности данного типа (из limits.h, stdint.h). Несовместимость таких типов с интерфейсами стандартной библиотеки и других библиотек. Наконец, среди встроенных типов есть полезные типа sig_atomic_t или intptr_t. И не факт, что I32 тут сработает, а не даст редкий но весьма заметный сбой. Да и эффективность машинного кода что в варианте 8/16->32, что 32->16/8 снижается.
> 19 Do not use expressions with side effects.
Звучит как "side effects" запрещены. Ибо они все в expressions. Функция -- это тоже expression как бы между прочим. Варианты вроде *s++ запрещать ещё более глупо. Ибо половина CPU имеют соответствующие машинные команды. И половина компиляторов не умеют толком переупорядочивать инструкции, для их использования, без явного вот такого указания.
> 20 Make only very limited use of the C pre-processor.
И выписывать всё то же самое руками? Маразм.
> 21 Do not define macros within a function or a block.
Бывает нужно именно так. Как же "Declare data objects at smallest possible level of scope."? В конце функции нужно не забывать #undef.
> *24 Place no more than one statement or declaration per line of text.
Есть две крайности. Это первая. А вторая -- по 20 операторов в строке. Код должен быть читаемым, а не похожим на ассемблер в столбик. И таки да, оператор запятая сильно повышает читаемость, вместо расписывания того же самого на пол-экрана. Когда нужно пару выражений в строчке (не операторов, это один оператор). Таки я соглашусь. One statement per line. Но не one expression.
Это
как
если
на
человеческом
языке
вот
так
выписывать.
> 73 All MISRA shall rules not already covered at Levels 1-4.
Дальше можно не читать. Считаю MISRA порядочным маразмом превращающим C в ассемблер.
Касательно NASA'овского. Маразма в целом меньше и есть ряд весьма здравых рекомендаций. goto не отрицают.
Игры с шириной таба до добра не доводят. TAB=8. Не нравится -- используй пробелы. Впрочем оно не нужно. Если у тебя 9 табов в экран не влазят уже -- твой говнокод пора выделить в отдельную функцию, а не изобретать таб уменьшенной ширины. Ибо все программы с котороыми приходится просматривать исходники -- не перенастроишь. А это не только IDE автора.
Комментарии обведённые в рамочки -- это маразм. Вообще когда лишний раз слишком упираются в визуальное оформление дальше можно не читать. Визуально оформлять нужно так, как автору данной (части) программы удобно. Если правишь чужой модуль -- приспосабливаться к авторскому стилю. Автору же стремиться использовать какие-то общие для проекта нормы, но не опускаться до маразма с измерением ширины таба.
CamelCase это отдельный маразм. ПотОм Ни АВтОр, Ни Кто дРуГой Уже нЕ ПомНиТ Что с КакОй БуКвЫ пиШетсЯ. И автодополнение работает не с первого раза. Более того, можно качественно обосраться получив два идентификатора, одинаково читаемых, но с разным регистром. Это правильно, что паскаль не чувствителен к регистру... Конкретно в C, на мой взгляд, CamelCase имеет право на жизнь только в случае, когда есть чёткие правила его использования (например, все объекты, переменные начинаются с маленькой буковки, а классы, конструкторы и т.п. с большой, когда оговорено, что в составных словах капитализируются только существительные или каждое отдельное слово), и когда есть необходимость CamelCase. А есть она в очень больших проектах только, где попросту без CamelCase становится сложно с длинными идентификаторами. Тем более нет смысла с помощью регистра выделять тип объекта -- он и так известен (ещё больший маразм -- венгерская нотация...)
Писать что-то осмысленное, как они предлагают program file prolog, в комментариях -- ЗА ЭТО СЖИГАТЬ НУЖНО. Потому, что потом программу меняют, в будущем, а неверный комментарий остаётся на всю жизнь. Лучше без комментариев, чем такие комментарии. Вообще не стоит вещь пытаться описать в двух разных местах, одно из которых никак не проверятся компилятором... Такие комментарии должны неразрывно быть связаны с декларациями. Если шибко неймётся -- писать как для doxygen и потом им же получить в html-файлике на одной страничке.
А уж Fortran-style архитектура с over9000 внешних переменных на входе и выходе -- точно сжигать. Лучше завести функции для получения каких-то внешних параметров в таком случае.
Вместо расставления скобочек вокруг оператора присваивания внутри while ((x=getchar())!=EOF) (что уже говнокод за который сжигать, ибо легко скобочки напутать) лучше таки освоить пресловутую запятую: while (x=getchar(), x!=EOF)...
[ZX]