Подтвердить что ты не робот

Имя параметра опущено, С++ 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?

4b9b3361

Ответ 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'