C99标准中的默认参数促销

时间:2012-08-17 15:45:43

标签: c function prototype c99 promotions

我对C99标准中的默认参数促销有疑问。在“C编程 - 现代方法,第2版”一书中,我读过:

  

参数转换:

     

[...]

     

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

     

2)编译器在调用之前没有遇到原型。编译器执行默认参数提升:(1)float参数转换为double。 (2)执行整体促销,使charshort参数转换为int。 (在C99中,执行整数提升。

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

  

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

那两个草书句子是不是彼此相反?我的意思是,如果C99禁止在没有先前声明/定义的情况下调用函数,它如何确定在那种函数调用中的促销?

3 个答案:

答案 0 :(得分:7)

不,他们不矛盾。

声明不一定是原型:

int f();

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

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

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

答案 1 :(得分: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

答案 2 :(得分:1)

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

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