【问题标题】:Default argument promotions according to C standards根据 C 标准的默认参数提升
【发布时间】:2020-09-01 18:45:43
【问题描述】:

我正在阅读默认参数提升的 C 标准,并且对很多问题感到困惑。 This question 以适当的方式显示了我怀疑的所有段落。

首先在第 6 段第 3 点中,它说如果原型以省略号结尾,则行为未定义。现在我的疑问是,如果我们谈论printf,它的原型也以省略号结尾,但它的行为不是未定义的,实际上它遵循第 6 段的第 1 点。标准在这里试图解释什么?并且进一步说,如果提升后的参数类型与参数的类型不兼容,则行为未定义。现在我的疑问是,如果参数已经在函数原型中声明为什么首先争论得到提升。

比第6段第4点,它说提升后的参数类型与提升后的参数类型不兼容,行为未定义。在这里,提到该函数没有原型,那么他们到底在谈论什么参数?以及如何提升参数。我只研究过论点提升。

比第 7 点第 1 段中的这一行意味着什么:将每个参数的类型作为其声明类型的非限定版本。

我真的很难理解这一切。如果你能用恰当的例子一一解释所有观点,那将是非常有帮助的。我不是以英语为母语的人,如果我对某些标准的观点有误解,也请指出错误。

【问题讨论】:

    标签: c prototype standards integer-promotion promotions


    【解决方案1】:

    在 C 1999 条款 6.5.2.2 第 6 段中,该问题中标记为 3 的项目旨在与标记为 1 的项目一起解释:如果 调用表达式 使用的类型没有原型,并且被调用函数定义为原型以省略号结尾或提升的参数类型与参数类型不兼容,则行为未定义。

    所以这并不是说你不能使用省略号,只是在调用函数的表达式中使用的函数类型与定义函数时使用的函数类型之间可能存在冲突。

    例子:

    文件 Caller.c 包含:

    void foo(); // No prototype (parameter types are not declared).
    
    int main(void)
    {
        foo(3, 4);
    }
    

    文件 Function.c 包含:

    void foo(int x,...) // Prototype (parameter types are declared) and has ellipsis.
    {
    }
    

    该行为未定义,因为 foo 被称为就像 void foo() 一样,但它是用 void foo(int x,...) 定义的。这种不匹配在现代实践中不应该发生,因为在没有原型的情况下声明函数是旧式的。它在 C 中仍然受支持,因此旧的源代码仍然可以编译,但新的源代码不应该使用它。只要在函数声明和函数定义中总是声明参数类型,那么这种情况就永远不会发生。

    在第 7 段中,“将每个参数的类型作为其声明类型的非限定版本”意味着忽略限定符(constvolatilerestrict_Atomic)。这意味着可以为 const int 参数传递 int 参数,依此类推。

    【讨论】:

    • 对于Ye Olde K&R C不熟悉的朋友,能否提供一个使用没有原型的类型调用表达式的例子?
    • “在调用函数的表达式中使用的函数类型和在定义函数中使用的函数类型之间可能存在冲突” - 我们在这里所说的function type 到底是什么意思?
    • @Noshi:函数的类型是它返回的类型加上它的参数类型的组合(或者缺少参数类型,对于老式的非原型方法)。这通常以int (char, double *) 之类的形式编写,用于返回int 的函数,其参数类型为char,另一个类型为指向double 的指针。 (在您需要特别处理函数类型的情况下,您可能更有可能看到指向此类函数的指针,int (*)(char, double *)。)
    猜你喜欢
    • 2020-09-02
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 2013-06-25
    • 1970-01-01
    • 2010-11-10
    相关资源
    最近更新 更多