Spec-Zone.ru › GCC 13

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, которая преобразует эти предупреждения в ошибки.

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

Spec-Zone.ru

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