Нужно ли следовать стандарту, принять стандарт С по этому вопросу?

17

В Stack Overflow есть очень опытные люди, которые всегда говорят о стандарте C. Людям, похоже, не нравятся непереносимые решения, даже если они работают на меня. Хорошо, я понимаю, что стандарт должен соблюдаться, но разве он не мешает творчеству программиста?

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

0decimal0
источник
7
Не могли бы вы уточнить, что вы подразумеваете под «стандартом»? Ты имеешь в виду, что не понимаешь поведения, которое не определено стандартом? Или не использовать расширения / функции компилятора? Или стилевые соглашения?
Их
1
@ikh Он принимает о стандартах ISO C (C90, C99, C11).
Aseem Bansal
9
Это то же самое, что сказать, что написание или говорение на английском языке, использование грамматики и словарного запаса английского языка, сковывает ваш творческий потенциал. Конечно, люди могут делать замечательные вещи, нарушая правила, за счет согласованности, но вы можете написать миллионы творческих книг, все еще придерживаясь «стандарта» английского языка.
Авнер Шахар-Каштан
Можете ли вы добавить пример «Люди, похоже, не любят непереносимые решения, даже если они работают на меня»?
BЈовић
1
@PHIfounder Просто для решения этого последнего случая вы можете опустить возврат из main, он неявно возвращает 0 :)
Daniel Gratzer

Ответы:

45

Есть несколько причин, почему придерживаться стандарта - это хорошо.

  1. Быть заблокированным в компиляторе - отстой. Вы полностью во власти группы разработчиков с их собственной повесткой дня. Они явно не хотят вас или чего-то еще, но если ваш компилятор начинает отставать от оптимизаций, новых функций, исправлений безопасности и т. Д., Слишком плохо; Вы застряли. В некоторых случаях некоторым компаниям приходится исправлять любой инструмент, от которого они сами зависят. Это огромная трата денег и времени, когда есть другие рабочие инструменты.

  2. Быть запертым на платформе - отстой. Если вы продвигаете программное обеспечение для Linux и хотите переключиться на Windows, потому что понимаете, что ваш рынок действительно существует, вам понадобится немало времени, чтобы изменить каждый непереносимый хак, который у вас есть в коде, для хорошей игры. как с GCC, так и с MSVC. Если у вас есть несколько частей вашего основного дизайна, основанного на чем-то подобном, удачи!

  3. Обратно несовместимые изменения сосет тяжелее всего. Стандарт никогда не нарушит ваш код (игнорировать python). Некоторые случайные авторы компиляторов могут решить, что на самом деле это дополнение для конкретной реализации не стоит проблем, и отбросить его. Если вам случится положиться на него, то вы застряли на любой старой версии, в которой она была последней.

Таким образом, главное сообщение, придерживающееся стандарта, делает вас более гибким . У вас конечно более ограниченный язык, но у вас больше

  • Библиотеки
  • Поддержка (люди знают стандарт, а не каждый сложный хак для конкретного компилятора)
  • Доступные платформы
  • Зрелые инструменты
  • Безопасность (будущее)

Это тонкий баланс, но полное игнорирование стандарта определенно является ошибкой. Я склонен организовывать свой C-код, чтобы полагаться на абстракции, которые могут быть реализованы непереносимым способом, но которые я могу прозрачно портировать, не меняя все, что зависит от абстракции.

Даниэль Гратцер
источник
+1 достаточно справедливо :), спасибо ... Я был серьезно смущен тем, как компиляторы немного отклонились от стандартов и заставил меня скептически относиться к строгому следованию ему, нужно было знать все за и против, и вы четко определили их.
0decimal0
6
Неопределенное поведение, вероятно, тоже отстой. С c довольно легко пойти в UB, если вы не будете строго следовать стандарту.
CodesInChaos
@CodesInChaos Согласовано, что неопределенное поведение прекрасно с одной стороны, так как оно допускает некоторые сумасшедшие оптимизации, но с другой - его отладку ...
Даниэль Гратцер
6

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

Итак, в чем преимущество следования стандарту, а не вашей собственной ментальной модели?

Проще говоря, это то, что стандарт верен, а ваша собственная ментальная модель неправильна. Ваша ментальная модель, как правило, представляет собой упрощенное представление о том, как все работает в вашей собственной системе, в общих случаях, когда все оптимизации компилятора отключены; Поставщики компиляторов, как правило, не прилагают усилий, чтобы соответствовать ему, особенно когда речь идет об оптимизации. (Если вы не задерживаете конец контракта, вы не можете ожидать какого-либо особого поведения от компилятора: мусор входит, мусор выходит.)

Людям, похоже, не нравятся непереносимые решения, даже если они работают на меня.

Может быть, лучше сказать, «даже если они, кажется, работают на меня». Если ваш компилятор специально не документирует, что данное поведение будет работать (то есть: если вы не используете обогащенный стандарт, состоящий из собственно стандарта плюс документация компилятора), вы не знаете, что он действительно работает или что он действительно надежен. Например, целочисленное переполнение со знаком обычно приводит к переносу во многих системах (так, INT_MAX+1как правило , есть INT_MIN), за исключением того, что компиляторы «знают», что целочисленная арифметика со знаком никогда не переполняется в (правильной) программе на C, и часто выполняют очень неожиданные оптимизации на основе этого » знание".

ruakh
источник
1
Вы можете скомпилировать -fwrapv, и тогда вы используете немного другой, нестандартный язык, в который всегда входит целочисленная арифметика со знаком.
user253751
@immibis: Когда C89 был написан, согласно его обоснованию, большинство современных компиляторов определили семантику тихого переноса для целочисленного переполнения. Во многих случаях наличие каких-либо гарантий относительно того, что происходит в случае целочисленного переполнения, может позволить коду быть более эффективным, чем это было бы возможно без таких гарантий, особенно если гарантии не доходят настолько далеко, чтобы предписывать точное поведение обтекания [точный Поведение обтекания можно эмулировать с использованием математики без знака, но семантика, которая является более свободной, но все же достаточной для удовлетворения требований, может позволить более эффективный код].
суперкат
@immibis: Жаль, что ревизионисты смогли убедить людей в том, что поведение, которое было реализовано почти единогласно среди компиляторов для определенных платформ (или в некоторых случаях единодушно на 100%), никогда не было «стандартным» на таких платформах, поскольку во многих случаях потеря эффективности из-за необходимости избегать такого поведения не будет компенсирована какими-либо «оптимизациями», которых компилятор смог достичь, отменив их.
суперкат
4

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

Нет. Стандарт сообщает, что разрешено делать. Если он не указан, вы находитесь на неопределенной территории поведения, и тогда все ставки отключены - программа может делать все что угодно.


Поскольку вы упомянули конкретный пример void main()против int main(), я могу улучшить свой ответ.

void main()не является стандартным объявлением основной функции. Он может работать на некоторых компиляторах через расширения, но зависит от реализации. Даже если это работает, вы должны проверить, делает ли это то, что вы хотите. Проблема в том, что разработчики компиляторов могут решить удалитьvoid main() следующем выпуске компилятора, что нарушит работу вашего приложения.

С другой стороны, стандарт четко определяет сигнатуру main int main()и указывает, что он должен делать.


С другой стороны, есть вещи, которые не определены в стандарте. Затем может применяться другой стандарт (например, POSIX). Лучший пример может быть с реализацией потоков в c ++ 03, поскольку стандартные программы c ++ 03 были однопоточными. В этом случае вы вынуждены использовать библиотеку, зависящую от платформы, или что-то вроде boost .

BЈовић
источник
4
Все, что делает компилятор, что не является стандартным, не является неопределенным поведением, расширения компилятора четко определены в том смысле, что они являются детерминированными и преднамеренными. UB нет.
Даниэль Гратцер
@jozefg То, как его спросили, - очевидно, что ОП задумал способ реализации UB. Например, потоки не были определены в c ++ 03.
BЈовић
1
@deworde: комментарий был удален из ответа.
Кевин
@jozefg Если конкретный компилятор всегда переносит целые числа со знаком, это можно считать недокументированным расширением языка. (Конечно, отсутствие документов означает, что у вас нет никаких гарантий, что вы не удалите расширение)
user253751
-6

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

Неизвестное
источник
2
без объяснения этот ответ может стать бесполезным в случае, если кто-то постит противоположное мнение. Например, если кто-то публикует заявление типа «следуйте правилам, если ваш проект касается специальных проектов, например, правительственного или армейского, но вам не нужно следовать правилам, если вы говорите об открытом исходном коде ...» Как этот ответ поможет читателю выбрать два противоположных мнения? Подумайте об изменении его в лучшую форму
комнат
2
Неизвестный: вы будете удивлены, узнав, сколько стандартов существует в правительственных проектах ...
Охотник на оленей