gpt4 book ai didi

c - C 中的默认参数和参数提升

转载 作者:行者123 更新时间:2023-12-03 14:32:13 25 4
gpt4 key购买 nike

我正在研究默认参数提升,并在某一时刻卡住了。在 C 2011 (ISO/IEC 9899:2011) 中,相关部分似乎是:

§6.5.2.2 Function calls

¶6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined. If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases:

— one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;

— both types are pointers to qualified or unqualified versions of a character type or void.



在段落的最后三行中,它讨论了在定义原型(prototype)时不包含原型(prototype)的函数类型。

它表示如果提升后的参数类型与提升后的参数类型不兼容,则行为未定义。

现在我有一个非常愚蠢的疑问,如果函数声明和函数定义都不包括本段中提到的原型(prototype),那么关于他们在段落的最后三行中讨论的参数。以及这里的“提升后的参数”是什么意思,因为我只研究过参数提升。什么是“参数促销”?

你也可以举出最后提到的异常(exception)情况的例子。如果有人可以用一个适当的例子来解释这一点,那将是非常可观的。

最佳答案

在 C 标准化之前(也就是在 C89 之前),函数的定义不同。为了向后兼容,C11 仍然支持该样式。除非整个目的是为了玩得开心,否则不要使用它:

int add_ints(); //forward-declaration has no parameters

add_ints(a, b)
//implicit type for return and parameters is int, this only works in pre-standard C or C89/C90
//int a, b; //remove this comment in C99/C11 for it to compile (also add return type int)
{
return a + b; //side note: old K&R compilers required parantheses around the return expression
}

在某种程度上,这些函数具有行为类似于可变参数的参数。调用者不知道函数需要什么参数(与可变参数相同)。它能够向它传递任何参数和任意数量的参数。但是,如果调用语句中的参数数量与声明中的参数数量不匹配,这当然是未定义的行为。

当然,由此产生一个问题。如果调用者想要传递 short ,它如何知道函数是否期待 short (并直接传递)或 int (并且需要转换它)?它不能,因此达成了共同点。已决定:
  • charshort晋升为 int
  • float晋升为 double

  • 以这种方式定义的所有函数(K&R 风格)和可变参数都会发生这种情况。这样,K&R 函数将永远不会期望 short参数,因此编译器将始终提升 short参数到 int .

    当然,正如@aschepler 所说,您仍然可以定义如下函数:
    short add_shorts(a, b)
    short a, b;
    {
    return a + b;
    }

    这意味着参数首先转换为 int并传递给函数,然后函数才将它们转换为 short并添加它们。

    小心像 printf() 这样的函数:
    printf("%.f", 3); //passes an int: UB and also wrong answer (my compiler prints 0)
    printf("%.f", 3.0); //correct
    printf("%.f", (double)3); //correct

    您实际上可能经常看到 K&R 函数,特别是如果作者没有注意添加 void不带参数的函数的关键字:
    int f1() //K&R function
    {
    return 0;
    }
    int f2(void) //Standard function
    {
    return 0;
    }

    int main(void) //Don't forget void here as well :P
    {
    int a = f1(); //Returns 0
    int b = f2(); //Returns 0
    int c = f1(100); //UB - invalid number of parameters, in practice just returns 0 :)
    int d = f2(100); //Compiler error - parameter number/types don't match

    //A good compiler would give a warning for call #3, but mine doesn't :(
    }

    编辑:不知道为什么,但是 cppreference将定义为 f1() 的函数分类为它们自己的函数类型(无参数,没有 void ),而不是 K&R 函数。我面前没有标准,但即使标准说同样的事情,他们也应该表现得一样,而且他们有我提到的历史。

    Default argument promotions

    Function declarations in C

    关于c - C 中的默认参数和参数提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61835509/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com