我是学习 C 编程语言的新手,这个问题让我感到困惑,因为我认为编译器会出错。
假设一个函数在其定义/原型出现之前被调用,关于它的参数,以下哪一项是错误的?
A. 所有 char 类型都转换为 int 类型。
B. 所有短类型都转换为 int 类型。
C. 所有浮点类型都转换为双精度类型。
D. 除 char、short 和 float 之外的所有类型都原封不动地传递。
E. 每个参数都被转换为其对应的形式参数的类型。
我是学习 C 编程语言的新手,这个问题让我感到困惑,因为我认为编译器会出错。
假设一个函数在其定义/原型出现之前被调用,关于它的参数,以下哪一项是错误的?
A. 所有 char 类型都转换为 int 类型。
B. 所有短类型都转换为 int 类型。
C. 所有浮点类型都转换为双精度类型。
D. 除 char、short 和 float 之外的所有类型都原封不动地传递。
E. 每个参数都被转换为其对应的形式参数的类型。
如果您在 C89 或 C90 中有函数调用(同样的事情;一个是 ANSI C,另一个是 ISO C),那么:
int
.char
( and signed char
and unsigned char
)和short
( and unsigned short
)被转换为int
unsigned int
unsigned short
sizeof(unsigned short) == sizeof(unsigned int)
float
double
printf()
您必须在范围内有一个原型才能正确调用 varargs 函数scanf()
。所以,答案是E。
标准(当前版本,ISO/IEC 9899:2011)说:
6.5.2.2 函数调用
¶6 如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有类型的参数
float
提升为双精度。这些称为默认参数提升。如果参数的数量不等于参数的数量,则行为未定义。如果函数是使用包含原型的类型定义的,并且原型以省略号 (, ...
) 或提升后的参数类型与参数类型不兼容,则行为未定义。如果函数定义的类型不包含原型,并且提升后的参数类型与提升后的参数类型不兼容,则行为未定义,但以下情况除外:
一种提升类型是有符号整数类型,另一种提升类型是对应的无符号整数类型,并且值可以在两种类型中表示;
这两种类型都是指向字符类型或
void
.
请注意,“错误”会导致未定义的行为,应不惜一切代价避免未定义的行为。该程序可以做任何事情——包括擦除计算机上的所有文件——根据标准这是可以接受的。实际上,程序很少这样做(甚至更很少会导致“恶魔从你的鼻子飞出”,导致短语“鼻恶魔”(搜索它),但面对未定义的行为也是可以接受的)。
如果可能的话,您应该制定一个政策,即永远不要在没有原型的情况下调用函数。所有新代码都应符合该标准;如果您不幸不得不维护不需要的古老代码,您可能不得不顺其自然,但目标是达到可以使用诸如-Wmissing-prototypes -Wstrict-prototypes -Wold-style-declaration -Wold-style-definition -Werror
效果之类的选项编译所有代码的地步。这些是报告函数原型和函数定义问题的 GCC 选项。
看看在进行函数调用时会发生什么,如果
1. 编译器在调用之前遇到了原型:
每个参数的值隐式转换为相应参数的类型,就像通过赋值一样。
2.编译器在调用之前没有遇到原型:
编译器将执行默认参数提升:(1)float
参数转换为double
. (2) 执行整数提升,导致char
和short
参数被转换为int
(在 C99 中,执行整数提升)。
所以答案是
E. 每个参数都被转换为其对应的形式参数的类型。
但请记住,依赖默认促销是危险的。考虑这个例子:
#include <stdio.h>
int main(void)
{
double x = 3.0;
printf("Square: %d\n", square(x));
return 0;
}
int square(int n)
{
return n*n;
}
在square
被调用的时候,编译器还没有看到原型,所以它不知道 square 需要一个 type 的参数int
。相反,编译器在 上执行默认参数提升x
,但没有效果。由于它需要一个类型的参数,int
但已经被赋予了一个double
值,所以调用的效果square
是undefined。
感谢大家!我找到了答案。
+所有子整数(char 和 short)都转换为 int 或 unsigned 类型。
+所有类型的float都转换为double类型。
+所有其他类型不变。
所以是的,答案是E。
感谢精神上的支持!