Может ли реализация, совместимая с ANSI C, включать дополнительные функции в свою стандартную библиотеку? - PullRequest
9 голосов
/ 11 сентября 2011

Разрешается ли реализация, совместимая с ANSI C, включать в свою стандартную библиотеку дополнительные типы и функции, помимо перечисленных в стандарте? (Идеальный ответ будет ссылаться на соответствующую часть стандарта ANSI.)

Я спрашиваю, в частности, потому что Mac OS 10.7 объявляет функцию getline в stdio.h, даже при компиляции с gcc или clang с использованием флага -ansi. Это ломает несколько старых программ, которые определяют свою собственную функцию getline. Это ошибка Mac OS 10.7? (Справочная страница для getline в Mac OS 10.7 говорит, что getline соответствует стандарту POSIX.1, вышедшему в 2008 году.)

Edit: чтобы уточнить, я нахожу странным, что включение stdio.h в программу ANSI C89 на Mac OS 10.7 также включает объявление для функции getline, поскольку getline не является одной из функций, перечисленных в K & R (и предположительно ANSI) описание stdio.h. В частности, попытка скомпилировать noweb :

gcc -ansi -pedantic    -c -o notangle.o notangle.c
In file included from notangle.nw:28:
getline.h:4: error: conflicting types for ‘getline’
/usr/include/stdio.h:449: error: previous declaration of ‘getline’ was here

Это ошибка в Mac OS 10.7, включающая объявление getline в stdio.h даже при компиляции для стандарта ANSI C89?

Ответы [ 2 ]

12 голосов
/ 11 сентября 2011

Из параграфа 7.1.3 параграфа 2 n1570 (который является проектом C1x):

Другие идентификаторы не зарезервированы.

Эта часть означает, что getline не должен определяться <stdio.h>, так как это не зарезервированный идентификатор в соответствии со спецификацией. Поэтому, если ваша библиотека определяет getline в <stdio.h>, это технически не соответствует стандарту C ...

Однако, вы должны иметь возможность использовать макросы функциональных тестов, чтобы getline был неопределенным в <stdio.h>.

#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>

Это даст вам только определения из более старых стандартов POSIX. Это не будет работать в некоторых реализациях GNU C ++, для некоторых людей EXTrEmeLY fruSTRaTiNG .

Соответствующий раздел справочной страницы (взят из справочной страницы glibc, извините ...)

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       getline(), getdelim():
           Since glibc 2.10:
               _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
           Before glibc 2.10:
               _GNU_SOURCE

Эта часть man-страницы сообщает вам, какие макросы нужно определить, для каких значений получить определение. Держу пари, что _POSIX_C_SOURCE уже определено вашим компилятором для 200809L.

Идея макросов функционального тестирования заключается в том, что если вы определяете свои макросы, такие как _POSIX_C_SOURCE, _BSD_SOURCE, _XOPEN_SOURCE и т. Д., Для значений, которые вы хотите, вам не нужно беспокоиться о конфликте новых библиотечных функций. с вашими существующими функциями. Существует также _GNU_SOURCE, который включает все , если вы используете glibc, но я предлагаю дать этому макросу широкое место.

4 голосов
/ 11 сентября 2011

Да, совместимой реализации разрешено определять дополнительные идентификаторы, включая функции, если они являются одним из зарезервированных идентификаторов в стандарте. Например:

  • Все идентификаторы, которые начинаются с символа подчеркивания и заглавной буквы или другого подчеркивание всегда зарезервировано для любого использования;

  • Все идентификаторы, которые начинаются с подчеркивания, всегда зарезервированы для использования в качестве идентификаторов. с областью действия файла как в обычном пространстве, так и в пространстве имен тега;

  • Все внешние имена, начинающиеся с is, to, str, mem или wcs, за которыми следует строчная буква;

Кроме того, есть имена, которые зарезервированы, только если вы включаете определенные заголовки; например, если вы включите <errno.h>, то он может определить любой макрос, начинающийся с E, за которым следует цифра или заглавная буква.

Однако getline() - это , а не такое зарезервированное имя, и совместимая реализация должна сделать его доступным для собственного использования программистом.

...