Имя параметра опущено, С++ vs C
В С++ я склонен игнорировать имя параметра при некоторых обстоятельствах. Но в C я получил ошибку, когда я опустил имя параметра.
Вот код:
void foo(int); //forward-decl, it OK to omit the parameter name, in both C++ and C
int main()
{
foo(0);
return 0;
}
void foo(int) //definition in C, it cannot compile with gcc
{
printf("in foo\n");
}
void foo(int) //definition in C++, it can compile with g++
{
cout << "in foo" << endl;
}
Почему? Не могу ли я указать имя параметра в определении функции C?
Ответы
Ответ 1
Нет, в C вы не можете пропустить идентификаторы параметров в определениях функций.
В стандарте C99 говорится:
[6.9.1.5] Если декларатор содержит список типов параметров, объявление каждого параметра должно содержать идентификатор, за исключением специальный случай списка параметров, состоящий из одного параметра типа void, и в этом случае идентификатор не должен быть. нет список деклараций должен следовать.
В стандарте С++ 14 говорится:
[8.3.5.11] Идентификатор может быть необязательно представлен как параметр имя; если он присутствует в определении функции, он называет параметр (иногда называемый "формальный аргумент" ). [Примечание: в частности, параметр имена также являются необязательными в определениях функций, а имена, используемые для параметр в разных объявлениях и определение функции не обязательно должны быть одинаковыми.]
Ответ 2
Причина в том, что то, что говорят соответствующие языковые стандарты, но есть обоснование разницы.
Если вы не укажете имя для параметра, то функция не может ссылаться на этот параметр.
В C, если функция игнорирует один из своих параметров, обычно имеет смысл просто удалить ее из декларации и определения и не передавать ее в каких-либо вызовах. Исключение может быть функцией обратного вызова, где набор функций должен быть одного типа, но не все из них обязательно используют их параметры. Но это не очень распространенный сценарий.
В С++, если функция выведена из функции, определенной в некотором родительском классе, она должна иметь такую же подпись, что и родительская, даже если дочерняя функция не используется для одного из значений параметра.
(Обратите внимание, что это не связано с параметрами по умолчанию, если параметр в С++ имеет значение по умолчанию, вызывающему абоненту не нужно передавать его явно, но определение функции все равно должно содержать имя, если оно собирается ссылаться к нему.)
Ответ 3
На чисто практическом уровне я имею дело с этим ежедневным. Лучшим решением на сегодняшний день является использование препроцессора. Мой общий заголовочный файл содержит:
//-------------------------------------------------------------------------
// Suppress nuisance compiler warnings. Yes, each compiler can already
// do this, each differently! VC9 has its UNREFERENCED_PARAMETER(),
// which is almost the same as the SUPPRESS_UNUSED_WARNING() below.
//
// We append _UNUSED to the variable name, because the dumb gcc compiler
// doesn't bother to tell you if you erroneously _use_ something flagged
// with __attribute__((unused)). So we are forced to *mangle* the name.
//-------------------------------------------------------------------------
#if defined(__cplusplus)
#define UNUSED(x) // = nothing
#elif defined(__GNUC__)
#define UNUSED(x) x##_UNUSED __attribute__((unused))
#else
#define UNUSED(x) x##_UNUSED
#endif
Примером использования UNUSED является:
void foo(int UNUSED(bar)) {}
Иногда вам действительно нужно обратиться к параметру, например, в инструкции assert() или debug. Вы можете сделать это через:
#define USED_UNUSED(x) x##_UNUSED // for assert(), debug, etc
Кроме того, полезно следующее:
#define UNUSED_FUNCTION(x) inline static x##_UNUSED // "inline" for GCC warning
#define SUPPRESS_UNUSED_WARNING(x) (void)(x) // cf. MSVC UNREFERENCED_PARAMETER
Примеры:
UNUSED_FUNCTION(int myFunction)(int myArg) { ...etc... }
и
void foo(int bar) {
#ifdef XXX
// ... (some code using bar)
#else
SUPPRESS_UNUSED_WARNING(bar);
#endif
}
Ответ 4
Вы можете опустить имя параметра в прототипе функции, но вы должны объявить его в реализации функции. Например, это компилируется и выполняется просто отлично под GCC 4.6.1
void foo(int, int);
void foo(int value, int secondValue)
{
printf("In foo with value %d and %d!\n", value, secondValue);
}
int main(int argc, char **argv)
{
foo(10, 15);
return 0;
}
Выходы: In foo with value 10 and 15!
Что касается (за исключением того, что стандарты говорят об этом): С++ позволяет вам вызывать функцию без использования всех аргументов, а C - нет. Если вы не передадите все аргументы функции в C, тогда компилятор будет бросать error: too few arguments to function 'foo'