当前位置:  开发笔记 > 编程语言 > 正文

最后命名参数不是函数还是数组?

如何解决《最后命名参数不是函数还是数组?》经验,为你挑选了1个好方法。

这个问题是关于vararg函数,以及省略号之前的最后一个命名参数:

void f(Type paramN, ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

我正在阅读C标准,并发现va_start宏的以下限制:

参数parmN是函数定义中变量参数列表中最右边参数的标识符(恰好在......之前).如果参数parmN使用寄存器存储类,函数或数组类型声明,或者使用与应用默认参数提升后生成的类型不兼容的类型,则行为未定义.

我想知道为什么以下代码的行为未定义

void f(int paramN[], ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

并且未定义以下内容

void f(int *paramN, ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

宏可以通过纯C代码实现.但纯C代码无法确定是否paramN声明为数组或指针.在这两种情况下,参数的类型都被调整为指针.功能类型参数也是如此.

我想知道:这个限制的理由是什么?在内部进行这些参数调整时,某些编译器是否存在实现此问题的问题?(C++也说明了相同的未定义行为 - 所以我的问题是关于C++的问题).



1> Michael Burr..:

对寄存器参数或函数参数的限制可能类似于:

您不能使用register存储类获取变量的地址.

函数指针有时与指向对象的指针完全不同.例如,它们可能比指向对象的指针大(您无法将函数指针可靠地转换为对象指针并再次返回),因此向函数指针的地址添加一些固定数字可能无法使您进入下一个参数.如果va_start()和/或va_arg()通过向地址添加一些固定数量来实现,paramN并且函数指针大于对象指针,则计算最终会va_arg()返回对象返回的错误地址.这似乎不是实现这些宏的好方法,但可能存在具有(甚至需要)此类实现的平台.

我想不出阻止允许数组参数会出现什么问题,但是PJ Plauger在他的书"标准C库"中这样说:

对定义的宏施加的一些限制似乎不必要地严重.对于某些实现,它们是.然而,每个都被引入,以满足至少一个严重的C实现的需要.

我想,很少有人比Plauger更了解C库的来龙去脉.我希望有人可以用一个实际的例子回答这个具体问题; 我认为这将是一个有趣的琐事.

新信息:


"国际标准的基本原理 - 编程语言 - C"说va_start():

parmN参数va_start旨在帮助实现者va_start完全用C语言编写一致的宏的定义,甚至使用前C89编译器(例如,通过获取参数的地址).对parmN参数声明的限制遵循允许这种实现的意图,因为如果参数的声明不符合这些限制,将&运算符应用于参数名称可能不会产生预期的结果.

这并不能帮助我限制数组参数.

推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有