Spec-Zone.ru › GCC 11

Далее: Сообщения об ошибках и предупреждениях, Предыдущее: Распространённые недоразумения с GNU C++, Вверх: Известные причины проблем с GCC [Оглавление][Индекс]

14.8 Изменения, которые мы не хотим вносить ¶

В этом разделе перечислены изменения, которые часто запрашивают пользователи, но которые мы не вносим, так как считаем, что GCC лучше без них.

  • Проверка количества и типов аргументов функции, имеющей устаревшее определение без прототипа.

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

  • Предупреждение об использовании выражения со знаком в качестве счётчика сдвига.

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

  • Предупреждение об присваивании значения со знаком беззнаковой переменной.

    Такие присваивания должны быть очень распространёнными; предупреждение об этом вызовет больше проблем, чем пользы.

  • Предупреждение, когда значение функции, отличной от void, игнорируется.

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

  • Установка -fshort-enums по умолчанию.

    Это приведёт к несовместимости структуры хранения с большинством других компиляторов C. И это не кажется очень важным, учитывая, что тот же результат можно получить другими способами. Самый важный случай — когда перечисление-значенное значение находится внутри структуры, и в этом случае вы можете явно указать ширину поля.

  • Установка по умолчанию для полей-битов беззнакового типа на некоторых машинах, где «стандарт ABI» предписывает это делать.

    Стандарт ISO C оставляет за реализацией право выбора, является ли поле-бит, объявленное как int, со знаком или без знака. Это фактически создаёт две альтернативные диалекты C.

    Компилятор GNU C поддерживает оба диалекта; вы можете указать диалект со знаком с помощью -fsigned-bitfields, а диалект без знака с помощью -funsigned-bitfields. Однако это оставляет открытым вопрос, какой диалект использовать по умолчанию.

    В настоящее время предпочтительным диалектом являются поля-биты со знаком, так как это проще. Поскольку int эквивалентно signed int во всех других контекстах, для них естественно, чтобы они были одинаковыми и в полях-битах.

    Некоторые производители компьютеров опубликовали стандарты двоичного интерфейса приложений, которые предписывают, что обычные поля-биты должны быть беззнаковыми. Однако ошибочно делать какие-либо заявления об этой проблеме в ABI. Это связано с тем, что обработка обычных полей-битов отличает два диалекта C. Оба диалекта имеют смысл на любом типе машины. То, был ли конкретный объектный файл скомпилирован с полями-битами со знаком или без знака, не имеет значения для других объектных файлов, даже если они обращаются к тем же полям-битам в тех же структурах данных.

    Программа написана на одном из этих двух диалектов. Программа имеет шанс работать на большинстве машин, если она скомпилирована с правильным диалектом. Она, вероятно, вообще не будет работать, если скомпилирована с неправильным диалектом.

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

    Иногда пользователи пишут программы, предназначенные только для определённого типа машины. В этих случаях пользователи выиграли бы, если бы компилятор GNU C по умолчанию поддерживал тот же диалект, что и другие компиляторы на этой машине. Но такие приложения редки. И пользователи, пишущие программу для работы на нескольких типах машин, не могут получить выгоду от такого рода совместимости.

    Вот почему GCC будет и впредь обрабатывать обычные поля-биты одинаково на всех типах машин (по умолчанию).

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

    (Конечно, пользователи, сильно озабоченные переносимостью, должны явно указывать в каждом поле-бите, со знаком оно или без знака. Таким образом, они пишут программы, которые имеют одинаковый смысл в обоих диалектах C.)

  • Отмена определения __STDC__ при отсутствии -ansi.

    В настоящее время GCC определяет __STDC__ безусловно. Это даёт хорошие результаты на практике.

    Программисты обычно используют условные операторы с __STDC__, чтобы узнать, безопасно ли использовать определённые функции ISO C, такие как прототипы функций или конкатенацию токенов ISO. Так как обычный gcc поддерживает все функции ISO C, правильный ответ на эти вопросы — «да».

    Некоторые пользователи пытаются использовать __STDC__ для проверки наличия определённых функций библиотеки. Это неправильное использование в программе ISO C, поскольку стандарт ISO C гласит, что соответствующая реализация самостоятельной среды должна определять __STDC__, даже если у неё нет функций библиотеки. ‘gcc -ansi -pedantic’ — это соответствующая реализация самостоятельной среды, и поэтому она должна определять __STDC__, даже если она не поставляется с библиотекой ISO C.

    Иногда люди говорят, что определение __STDC__ в компиляторе, который не полностью соответствует стандарту ISO C, каким-то образом нарушает стандарт. Это нелогично. Стандарт — это стандарт для компиляторов, которые утверждают, что поддерживают ISO C, например, ‘gcc -ansi’, а не для других компиляторов, таких как обычный gcc. То, что говорит стандарт ISO C, относится к проектированию обычного gcc без -ansi только по прагматическим соображениям, а не как требование.

    GCC обычно определяет __STDC__ как 1, а также определяет __STRICT_ANSI__, если вы укажете опцию -ansi или опцию -std для строгого соответствия какой-либо версии ISO C. На некоторых хостах системные заголовочные файлы используют другую конвенцию, где __STDC__ обычно 0, но 1, если пользователь указывает строгое соответствие стандарту C. GCC следует конвенции хоста при обработке системных заголовочных файлов, но при обработке пользовательских файлов следует обычной конвенции GNU C.

  • Отмена определения __STDC__ в C++.

    Программы, написанные для компиляции с помощью трансляторов C++ в C, получают значение __STDC__, которое соответствует компилятору C, который используется впоследствии. Эти программы должны проверять __STDC__, чтобы определить, какой тип препроцессора C использует компилятор: следует ли конкатенировать токены в стиле ISO C или в традиционном стиле.

    Эти программы правильно работают с GNU C++ при условии, что __STDC__ определён. В противном случае они не будут работать.

    Кроме того, многие заголовочные файлы написаны так, чтобы предоставлять прототипы в ISO C, но не в традиционном C. Многие из этих заголовочных файлов могут работать без изменений в C++, при условии, что __STDC__ определён. Если __STDC__ не определён, все они потерпят неудачу и все потребуют изменения для явной проверки на C++.

  • Удаление «пустых» циклов.

    Исторически GCC не удалял «пустые» циклы, исходя из предположения, что наиболее вероятная причина их включения в программу — создание задержки, так что их удаление не ускорит реальные программы.

    Однако логика заключается в том, что оптимизация непустого цикла не может привести к пустому. Это было справедливо для тщательно написанного C, скомпилированного менее мощными оптимизаторами, но не всегда верно для тщательно написанного C++ или с более мощными оптимизаторами. Таким образом, GCC удаляет операции из циклов всякий раз, когда может определить, что эти операции не видны извне (кроме, конечно, времени, затраченного на их выполнение). В случае, если цикл может быть доказан как конечный, GCC также удалит сам цикл.

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

    {
       int sum = 0;
       int ix;
    
       for (ix = 0; ix != 10000; ix++)
          sum += some_expression;
    }

    Хотя sum накапливается в цикле, сумма не используется, поэтому накопление можно удалить.

  • Приведение побочных эффектов к тому же порядку, что и в некоторых других компиляторах.

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

    void func (int, int);
    
    int i = 2;
    func (i++, i++);

    Нет гарантии (ни в стандарте языка C, ни в стандарте языка C++), что инкременты будут вычислены в каком-либо определённом порядке. Любой инкремент может произойти первым. func может получить аргументы ‘2, 3’, или ‘3, 2’, или даже ‘2, 2’.

  • Превращение некоторых предупреждений в ошибки по умолчанию.

    Некоторые тестовые наборы ISO C сообщают об ошибке, когда компилятор не выводит сообщение об ошибке для определённой программы.

    ISO C требует сообщения «диагностики» для определённых типов некорректных программ, но предупреждение определяется GCC как диагностическое сообщение. Если GCC выводит предупреждение, но не ошибку, это корректная поддержка ISO C. Если тестовые наборы называют это «ошибкой», их следует запускать с опцией GCC -pedantic-errors, которая превратит эти предупреждения в ошибки.

Далее: Сообщения об ошибках и предупреждениях, Предыдущее: Распространённые недоразумения с GNU C++, Вверх: Известные причины проблем с GCC [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/Non-bugs.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API