Spec-Zone.ru › GCC 15

15.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-15.3.0/gcc/Non_002dbugs.html

Spec-Zone.ru

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