1

我是学习 C 编程语言的新手,这个问题让我感到困惑,因为我认为编译器会出错。

假设一个函数在其定义/原型出现之前被调用,关于它的参数,以下哪一项是错误的?

A. 所有 char 类型都转换为 int 类型。

B. 所有短类型都转换为 int 类型。

C. 所有浮点类型都转换为双精度类型。

D. 除 char、short 和 float 之外的所有类型都原封不动地传递。

E. 每个参数都被转换为其对应的形式参数的类型。

4

3 回答 3

4

如果您在 C89 或 C90 中有函数调用(同样的事情;一个是 ANSI C,另一个是 ISO C),那么:

  • 返回类型假定为int.
  • 类型char( and signed charand unsigned char)和short( and unsigned short)被转换为intunsigned intunsigned shortsizeof(unsigned short) == sizeof(unsigned int)floatdouble
  • 请注意,指针不会更改。
  • 假定该函数不是可变参数函数。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 选项。

于 2013-11-01T21:40:25.000 回答
0

看看在进行函数调用时会发生什么,如果

1. 编译器在调用之前遇到了原型:

每个参数的值隐式转换为相应参数的类型,就像通过赋值一样。

2.编译器在调用之前没有遇到原型:

编译器将执行默认参数提升:(1)float参数转换为double. (2) 执行整数提升,导致charshort参数被转换为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值,所以调用的效果squareundefined

于 2013-11-01T21:48:15.800 回答
0

感谢大家!我找到了答案。

+所有子整数(char 和 short)都转换为 int 或 unsigned 类型。

+所有类型的float都转换为double类型。

+所有其他类型不变。

所以是的,答案是E。

感谢精神上的支持!

于 2013-11-01T22:08:58.703 回答