根据 C 标准进行默认参数升级



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

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

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

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

我真的很难理解这一切。如果您能用适当的示例一一解释所有要点,那将非常有帮助。我的母语不是英语,如果我误解了某些标准的观点,也请指出错误。

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

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

例:

File Caller.c 包含:

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

File 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参数,依此类推。

最新更新