我在阅读C标准的默认论点推广时,对很多点感到困惑。这个 这个问题以适当的方式展示了所有我有疑问的段落。
首先在第6段第3点,它说如果原型以省略号结尾,那么行为是未定义的。现在我的疑问是,如果我们谈论 printf
它的原型也是以省略号结尾的,但它的行为并不是没有定义的,事实上它遵循了第6段的第1点。标准想解释的是什么呢,它还说如果 推广后的参数类型与参数类型不兼容,行为未定义.. 现在我的疑问是,如果参数已经在函数原型中声明了,为什么首先要提升参数。
在第6段第4点中说到 晋升后的参数类型与晋升后的参数类型不一致,行为未定义。. 由于这里提到了函数没有原型,那么到底他们说的是什么参数呢?以及参数如何晋升。我只研究过参数的提升。
比起第7段第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段中,"把每个参数的类型作为其声明类型的非限定versio "的意思是忽略限定符(const
, volatile
, restrict
或 _Atomic
). 这意味着可以通过一个 int
争论 const int
参数,以此类推。