имя параметра опущено, C ++ против C - PullRequest
36 голосов
/ 08 января 2012

В C ++ я склонен опускать имя параметра при некоторых обстоятельствах.Но в C я получил ошибку, когда пропустил имя параметра.

Вот код:

void foo(int);  //forward-decl, it's OK to omit the parameter's 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?

Ответы [ 4 ]

34 голосов
/ 08 января 2012

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

Стандарт C99 гласит:

[6.9.1.5] Если декларатор включает список типов параметров, объявление каждого параметра должно включать идентификатор, за исключением особый случай списка параметров, состоящего из одного параметра типа void, в этом случае не должно быть идентификатора. нет Список объявлений должен следовать.

Стандарт C ++ 14 гласит:

[8.3.5.11] При необходимости в качестве параметра может быть указан идентификатор название; если присутствует в определении функции, он называет параметр (иногда называется «формальный аргумент»). [Примечание: в частности, параметр имена также необязательны в определениях функций и имена, используемые для параметр в разных объявлениях и определение функции не должно быть таким же.]

16 голосов
/ 08 января 2012

Причина в том, что именно об этом говорят соответствующие языковые стандарты, но есть причина для различия.

Если вы не предоставите имя для параметра, то функция не может ссылаться на этот параметр.

В C, если функция игнорирует один из своих параметров, обычно имеет смысл просто удалить его из объявления и определения и не передавать его ни при каких вызовах. Исключением может быть функция обратного вызова, где набор функций должен быть одного типа, но не все из них обязательно используют свои параметры. Но это не очень распространенный сценарий.

В C ++, если функция является производной от функции, определенной в некотором родительском классе, она должна иметь такую ​​же сигнатуру, что и родительская функция, даже если дочерняя функция не использует одно из значений параметра.

(Обратите внимание, что это не связано с параметрами по умолчанию; если параметр в C ++ имеет значение по умолчанию, вызывающая сторона не должна передавать его явно, но определение функции по-прежнему должно предоставлять имя, если оно будет ссылаться к нему.)

5 голосов
/ 11 января 2012

На чисто практическом уровне я имею дело с этим ежедневно.Наилучшим решением на сегодняшний день является использование препроцессора.Мой общий заголовочный файл содержит:

//-------------------------------------------------------------------------
//  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 ()или отладочный оператор.Вы можете сделать это с помощью:

#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 голосов
/ 08 января 2012

Вы можете опустить имя параметра в прототипе функции, но вы должны объявить его в реализации функции.Например, он компилируется и прекрасно работает в соответствии с 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 - нет.Если вы не предоставите все аргументы функции в C, то компилятор выдаст error: too few arguments to function 'foo'

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