У меня есть файл заголовка, который содержит
#define PROTOTYPE(s) s
Какой в этом смысл? Похоже, он просто заменит ввод самим собой.
Есть множество других директив вокруг него, но только один , который , как представляется , есть какой - либо подшипник только что проверил , если он определен: #ifndef PROTOTYPE
. Я нашел несколько мест в заголовочных файлах HDF4 , которые делают это: #define PROTOTYPE
. Так что ничего из этого не проясняет мой вопрос. По-прежнему кажется довольно бесполезным.
Вот как это используется:
CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));
Это часть проекта, в котором используется Sybase Open Client. clientmsg_callback здесь позже используется:
ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *)clientmsg_callback);
Я выхожу из примера программы отсюда:
clientmsg_callback будет реализован позже. Я думаю, что образец изначально был написан с учетом C, а не C ++. Возможно, это как-то связано с этим?
#if
/#ifdef
/#ifndef
/,#else
где вместо этого могло бы быть другое определение? Это может иметь значение при использовании в других макросах, особенно рядом с#
или##
. Это могло быть просто для стиля комментирования. Недостаточно контекста, чтобы действительно ответить.PROTOTYPE
. Если вы видите в коде странные определения, которые кажутся бесполезными, подумайте о потенциальной гибкости, если кто-то хочет что-то изменить для удобства.Ответы:
В былые времена действительно, очень раннего C, не существовало такой вещи, как прототип. Списки аргументов функции идут после скобок функции, например :
square(x) int x; { int y = x * x; return y; }
В наши дни, конечно, аргументы заключаются в круглые скобки:
square(int x) { int y = x * x; return y; }
Обратите внимание на тип возвращаемого значения «отсутствует»; Функции C использовались для неявного возврата
int
, и только если вам нужен был другой тип возврата, вы должны были сказать, что это было.У объявлений функций был еще один набор правил. Объявление функции в K&R C (древняя версия) не имело аргументов:
int square();
А прототипы функций в ANSI C имеют список аргументов:
int square(int x);
Во время перехода люди использовали дурацкие макросы, чтобы они могли компилировать обоими способами:
int square(PROTOTYPE(int x));
С участием
#define PROTOTYPE(s)
это расширится до первой версии.
С участием
#define PROTOTYPE(s) s
он расширится до второго.
Что касается «лишних» скобок в коде вопроса, они необходимы, когда в списке аргументов более одного аргумента. Без них вызов макроса имеет более одного аргумента, поэтому не будет соответствовать макросу, определенному только с одним аргументом:
PROTOTYPE(int x, int y) // error: too many arguments PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)
источник
#define PROTOTYPE(s)
с входомint x;
преобразуемыйx
? Мне кажется, что это завершается пустой строкойzlib.h
заголовке библиотеки zlib сOF()
макросом: github.com/madler/zlib/blob/master/zlib.hzconf.h
.Подобные макросы будут использоваться в прототипах в файле заголовка, чтобы сделать что-то вроде этого:
int foo PROTOTYPE((int bar));
Если был обнаружен ANSI C (
__STDC__
определен как 1), это расширилось бы до:int foo(int bar);
Если ANSI C не был обнаружен, это расширилось бы до:
int foo();
что было распространено до стандартизации C.
Некоторые библиотеки до сих пор это делают; если вы заглянете внутрь
tcpd.h
(если он у вас есть), вы увидите:Это хорошо объясняет.
Что касается двойных скобок, это
__P(arg1, arg2)
приведет к синтаксической ошибке (передача макросу слишком большого количества аргументов), а__P((arg1, arg2))
будет нормально (только один заключен в круглые скобки).Это похоже на
__extension__((...))
GNU C. В компиляторах, отличных от GNU, просто#define __extension__(unused)
иметь полупереносимый код, поскольку дается только один «аргумент», заключенный в круглые скобки.источник