Совместима ли C99 с C89?
Я привык к старому стилю C и только недавно начал изучать особенности c99. У меня только один вопрос: будет ли моя программа успешно скомпилирована, если я использую в своей программе c99, флаг c99 с gcc
и связать его с предыдущими библиотеками c99?
Итак, я должен придерживаться старого C89 или развиваться?
8 ответов
Я считаю, что они совместимы в этом отношении. Это до тех пор, пока материал, с которым вы компилируете, не наступит ни на одну из новых вкусностей. Например, если старый код содержит enum bool { false, true };
тогда у вас проблемы. Как подобный динозавр, я медленно обнимаю чудесный новый мир C99. В конце концов, это было всего лишь около 10 лет;)
Вы должны развиваться. Спасибо за внимание:-)
На самом деле, я остановлюсь на этом.
Вы правы, что C99 существует уже довольно давно. Вы должны (на мой взгляд) использовать этот стандарт для всего, кроме устаревшего кода (где вы просто исправляете ошибки, а не добавляете новые функции). Это, вероятно, не стоит для унаследованного кода, но вы должны (как и во всех бизнес-решениях) провести собственный анализ затрат / выгод.
Я уже гарантирую, что мой новый код совместим с C1x - хотя я еще не использую какие-либо новые функции, я стараюсь убедиться, что он не сломается.
Что касается кода, на который нужно обратить внимание, авторы стандартов очень серьезно относятся к обратной совместимости. Их работа никогда не заключалась в разработке нового языка, а в том, чтобы кодифицировать существующие практики.
Фаза, в которой они находятся в данный момент, дает им больше свободы в обновлении языка, но они по-прежнему следуют клятве Гиппократа с точки зрения результатов: "Прежде всего, не навреди".
Как правило, если ваш код нарушен новым стандартом, компилятор вынужден сообщить вам об этом. Так что простая компиляция вашей базы кода будет отличным началом. Однако, если вы прочитаете обоснование C99, вы увидите фразу "тихие изменения" - это то, что вам нужно остерегаться.
Это поведенческие изменения в компиляторе, о которых вам не нужно сообщать, и они могут стать источником сильного беспокойства и скрежета зубов, если ваше приложение начинает вести себя странно. Не беспокойтесь о битах "тихого изменения в c89" - если бы они были проблемой, они бы вас уже укусили.
Этот документ, кстати, отлично читается, чтобы понять, почему фактический стандарт говорит то, что он говорит.
Некоторые функции C89 не действительны C99
Возможно, эти функции существуют только по историческим причинам, и их не следует использовать в современном коде C89, но они существуют.
Стандартное черновое предисловие C99 N1256, параграф 5, сравнивает C99 со старыми ревизиями и является хорошим местом для начала поиска этих несовместимостей, даже несмотря на то, что он имеет гораздо больше расширений, чем ограничений.
Неявное возвращение int и типы переменных
Упоминается Лутцем в комментарии, например, следующие действительны C89:
static i;
f() { return 1; }
но не C99, в котором вы должны написать:
static int i;
int f() { return 1; }
Это также исключает вызов функций без прототипов в C99: нужны ли прототипы для всех функций в C89, C90 или C99?
N1256 говорит:
удалить неявный int
Возврат без выражения для не пустой функции
Действительный C89, недействительный C99:
int f() { return; }
Я думаю, что в C89 он возвращает значение, определенное реализацией. N1256 говорит:
возврат без выражения не разрешен в функции, которая возвращает значение
Целочисленное деление с отрицательным операндом
- C89: округляет до определенного направления реализации
- C99: округляет до 0
Так что если ваш компилятор округлен до -inf
и вы полагались на поведение, определяемое реализацией, теперь ваш компилятор вынужден нарушать ваш код на C99.
/questions/27598215/kakovo-povedenie-tselochislennogo-deleniya/27598231#27598231
N1256 говорит:
надежное целочисленное деление
Совместимость с Windows
Одной из основных практических проблем является возможность компиляции в Windows, поскольку Microsoft не намерена внедрять C99 слишком рано.
Именно поэтому, например, libgit2 ограничивает допустимые функции C99.
С уважением: попробуйте и узнайте.:-)
Тем не менее, имейте в виду, что даже если вам нужно исправить несколько небольших различий в компиляции, вероятно, стоит подняться вверх.
Соглашения о вызовах между библиотеками C давно не менялись, и на самом деле, я не уверен, что это когда-либо изменилось.
На данный момент операционные системы в значительной степени полагаются на соглашения о вызовах C, поскольку API C, как правило, являются связующим звеном между частями ОС.
Таким образом, в основном ответ таков: "Да, двоичные файлы будут обратно совместимы. Нет, естественно, код, использующий функции C99, не может быть позже скомпилирован с компилятором не-C99".
Если вы не нарушите явные функции C99, код c90 будет отлично работать с флагом c99 с другими предыдущими библиотеками c99.
Но в C89 есть некоторые библиотеки, основанные на DOS, которые не будут работать.
C99 очень гибкий, поэтому не стесняйтесь мигрировать:-)
Он предназначен для обратной совместимости. Он формализует расширения, которые уже реализованы многими поставщиками. Возможно, даже возможно, что хорошо написанная программа не будет иметь проблем при компиляции с C99.
По моему опыту, перекомпиляция некоторых модулей, а не других, чтобы сэкономить время... тратит много времени. Обычно есть некоторые легко пропускаемые детали, которым нужен новый компилятор, чтобы все это было совместимо.
Существует несколько частей стандарта C89, которые написаны неоднозначно, и в зависимости от того, как интерпретировать правило о типах указателей и объектах, к которым они обращаются, стандарт можно рассматривать как описание одного из двух очень разных языков - одного из которых семантически гораздо более мощный и, следовательно, может использоваться в более широком диапазоне областей, и одно из которых предоставляет больше возможностей для оптимизации на основе компилятора. Стандарт C99 "прояснил" правило, чтобы прояснить, что он не предпринимает никаких усилий для обеспечения совместимости с прежним языком, даже несмотря на то, что он был в подавляющем большинстве одобрен во многих областях; он также рассматривает как неопределенные некоторые вещи, которые были определены в C89, но только потому, что правила C89 не были написаны достаточно точно, чтобы запретить их (например, использование memcpy
для типа punning в случаях, когда у места назначения есть продолжительность кучи).
Таким образом, C99 может быть совместим с языком, который, по мнению его авторов, был описан C89, но не совместим с языком, который обрабатывался большинством компиляторов C89 в течение 1990-х годов.