在声明者之外声明参数

som*_*guy 7 c function

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;
}
Run Code Online (Sandbox Code Playgroud)

这里是int a,b; 是参数的声明列表.这两个定义之间的区别在于第一个表单充当原型声明,强制将后续调用的参数转换为函数,而第二个表单则不然.

这对程序员意味着什么,它是否会影响编译器生成的代码?

Oli*_*rth 11

这意味着在第二种情况下,调用者有责任确保提供的参数类型正确; 不会提供隐式转换(默认参数促销除外).从6.5.2.2节:

如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升.

...

如果表示被调用函数的表达式具有包含原型的类型,则将参数隐式转换为相应参数的类型,就像通过赋值一样.

所以调用这样的代码就可以了:

char   x = 3;
char   y = 7;
max(x, y);  // Equivalent to max((int)x, (int)y)
Run Code Online (Sandbox Code Playgroud)

因为x并且在被放置到堆栈之前被y提升int.

但是,像这样的代码是不可行的:

double x = 3.0;
long   y = 7;
max(x, y);  // Uh-oh
Run Code Online (Sandbox Code Playgroud)

x并将y作为double和放置在堆栈上long,但max()会尝试读取两个ints,这将导致未定义的行为(实际上,原始位将被重新解释).

这是不使用第二种形式的一个原因; 它在标准中的唯一原因是提供与(极端)遗留代码的向后兼容性.如果您正在使用GCC,则可以使用-Wold-style-definition标志强制执行此操作; 我希望其他编译器提供相同的东西.