Является ли следующая программа строго соответствующей программе C99? - PullRequest
6 голосов
/ 15 февраля 2010

Название почти говорит само за себя, но я перефразирую вопрос ...

Является ли следующая программа "строго соответствующей программе" по стандарту C99?

#include <stdlib.h>
/* Removing any pre-existing macro definition, in case one should exist in the implementation.
 * Seems to be allowed under 7.1.3 para 3, as malloc does not begin with _X where X is any  capital letter.
 * And 7.1.4 para 1 explicitly permits #undef of such macros.
 */
#ifdef malloc    
#undef malloc     
#endif            

/* Macro substitution has no impact on the external name malloc
 * which remains accessible, e.g., via "(malloc)(s)".  Such use of
 * macro substitution seems enabled by 7.1.4 para 1, but not specifically
 * mentioned otherwise.
 */
void * journalling_malloc(size_t size);
#define malloc(s)     ((journalling_malloc)(s))      

int main(void)
{
    return malloc(10) == NULL ? 1 : 0;     
    /* Just for the sake of expanding the 
     * macro one time, return as exit code
     * whether the allocation was performed. 
     */
}

Ответы [ 4 ]

11 голосов
/ 16 февраля 2010

Давайте посмотрим, что говорит об этом стандарт C99:

См. 7.1.3, § 1, пункт 5:

Каждый идентификатор с областью файла, указанной в любом из следующих подпунктов [...], зарезервирован для использования в качестве имени макроса и в качестве идентификатора с областью файла в том же пространстве имен , если любой из связанных с ним заголовков включен .

Поскольку вы включаете stdlib.h, имя malloc зарезервировано для использования в качестве имени макроса.

Но 7.1.4, §1 позволяет использовать #undef для зарезервированных имен:

Использование #undef для удаления любого определения макроса также гарантирует, что фактическая функция называется.

Это позволяет повторно #define malloc, что приводит к неопределенному поведению в соответствии с 7.1.3, §2:

Если программа [...] определяет зарезервированный идентификатор как имя макроса, поведение не определено .

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

На практике с вами должно быть все в порядке, если ваше определение malloc удовлетворяет всем положениям, предусмотренным стандартом для библиотечной функции, что может быть достигнуто путем переноса фактического вызова в malloc().

3 голосов
/ 15 февраля 2010

Вам нужно изменить journalling_malloc(...) с void на void *, изменить комментарии на // (потому что они комментируют вашу undef) и добавить #endif в верхней части, но в остальном это выглядит нормально ,

1 голос
/ 15 февраля 2010

Будет ли работать: да.

Соответствует ли он: нет.

Согласно стандарту C:

http://www.open -std.org / jtc1 / sc22 / wg14 / www / docs / n1124.pdf

Все имена в стандартной библиотеке зарезервированы (включая malloc).

7.1.3 Reserved identifiers
Specifically:  
    <quote>Each macro name in any of the following subclauses</quote>
    <quote>All identifiers with external linkage in any of the
    following subclauses</quote>

Также строго соответствующая программа не может определять имена, которые зарезервированы для реализации (т. Е. Это включает зарезервированные имена и идентификаторы, те, что для текущих библиотек, и те, которые зарезервированы для будущего использования).

7.1.3 (note 2)
Specifically:
    <quote>If the program declares or defines an identifier in a context in which
    it is reserved or defines a reserved identifier as a macro name,
    the behavior is undefined.</quote>

Таким образом, по определению: определение malloc () не соответствует, потому что это неопределенное поведение (незаконно).

0 голосов
/ 15 февраля 2010

Идентификаторы макросов являются собственными именами, и всем идентификаторам библиотек любого вида запрещено наложение псевдонимов на макрос независимо от языкового статуса макросов.

§6.10.3 / 7

Идентификатор, следующий сразу определение называется именем макроса. Существует одно пространство имен для макроса имена.

§7.1.3 / 1

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

§7.1.3 / 2

Если программа объявляет или определяет идентификатор в контексте, в котором он зарезервировано (кроме как разрешено 7.1.4), или определяет зарезервированный идентификатор как имя макроса, поведение не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...