4

我对 C99 标准中的默认参数提升有疑问。在“C Programming - A Modern Approach, 2nd Edition”一书中,我读到:

参数转换:

[...]

1)编译器在调用之前遇到了原型。[...]

2)编译器在调用之前没有遇到原型。编译器执行默认参数提升:(1)float参数转换为double. (2) 执行积分提升,导致charshort参数被转换为int。(在 C99 中,执行整数提升。

几行进一步显示了一个示例,其中在调用之前没有函数原型或定义。评论如下:

当然,更好的解决方案是square在调用它之前提供一个原型。在 C99 中,在square没有首先提供函数的声明或定义的情况下调用是错误的。

这两个草书的句子是不是有点相反?我的意思是,如果 C99 禁止在没有事先声明/定义的情况下调用函数,它如何确定这种函数调用中的提升?

4

3 回答 3

7

不,它们并不矛盾。

声明不一定是原型:

int f();

声明了函数f但不是原型,因为对参数类型一无所知。

int (a)
 in a;
{
 ...
}

是一个定义,但也不是原型。

于 2012-08-17T15:55:25.613 回答
2

C99 并没有禁止你调用没有原型的函数。

我无法提供详细信息,因为您尚未发布代码square()或对其的调用,但可能正在发生的事情是对调用中的参数进行的提升square()导致传递给函数的类型与实际声明的类型不同在实施中。

将导致未定义的行为,并且将是一个错误。

例如:

// in foo.c:

int foo(void)
{ 
    char x = 42;

    return square(x); // x is promoted to int, but is wrong
}


// in bar.c

#include <stdio.h>
void bar(int x)
{ 
    square( &x); // this call is fine -  what is being passed is what square() expects
    printf("The result is %d\n", x);
}


// in square.c

void square( int* p)
{
    *p *= *p;
    return;
}

如果square()使用声明参数的原型定义为具有类型的参数char,则在调用代码没有“看到”原型的情况下无法正确调用它,因为在这种情况下,参数将被提升为int.

于 2012-08-17T15:58:23.083 回答
1

如果没有在 C99 中提供事先声明或定义,我找不到任何关于调用函数的错误。

关闭的事情似乎是不再假定默认返回类型 int 。即声明foo(int a);在 C99 之前是允许的,但在 C99 中是错误的。C99之前的意思int foo(int a);

于 2012-08-17T17:02:33.373 回答