Объявление параметров вне декларатора - PullRequest
7 голосов
/ 22 января 2012

Стандарт C устанавливает, что для определения функции , если декларатор включает список идентификаторов, типы параметров должны быть объявлены в следующем списке объявлений. * extern int max(int a, int b) { return a > b ? a : b; } extern int max(a, b) int a, b; { return a > b ? a : b; } Здесь int a, b; список объявлений для параметров. Разница между этими двумя определениями заключается в том, что первая форма действует в качестве объявления прототипа, который вызывает преобразование аргументов последующие вызовы функции, тогда как вторая форма - нет.

Что это значит для программиста и влияет ли это на код, создаваемый компилятором?

1 Ответ

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

Это означает, что во втором случае вызывающая сторона несет ответственность за то, чтобы указанные аргументы имели правильный тип; неявное преобразование не будет предоставлено (кроме продвижения аргументов по умолчанию). Из раздела 6.5.2.2:

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

...

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

Значит, такой код вызова будет в порядке:

char   x = 3;
char   y = 7;
max(x, y);  // Equivalent to max((int)x, (int)y)

потому что x и y повышаются до int до помещения в стек.

Однако код, подобный этому, не будет в порядке:

double x = 3.0;
long   y = 7;
max(x, y);  // Uh-oh

x и y будут помещены в стек как double и long, но max() попытается прочитать два int s, что приведет к неопределенному поведению (на практике необработанные биты будут переинтерпретированы).

Это одна из причин не использовать вторую форму; единственная причина, по которой он входит в стандарт, заключается в обеспечении обратной совместимости с (чрезвычайно) устаревшим кодом. Если вы используете GCC, вы можете применить это с помощью флага -Wold-style-definition; Я надеюсь, что другие компиляторы предложат что-то эквивалентное.

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