Python文档声称以下内容不适用于“某些平台或编译器”:
int foo(int); // Defined in another translation unit.
struct X { int (*fptr)(int); } x = {&foo};
具体来说,Python文档说:
我们想把它分配到tp_new插槽,但我们不能,因为 可移植性,在某些平台或编译器上,我们不能静态 使用另一个C中定义的函数初始化结构成员 因此,我们将在模块中分配tp_new插槽 在调用PyType_Ready()之前初始化函数。 - http://docs.python.org/extending/newtypes.html
以上标准C89和/或C99?什么编译器具体无法处理上述内容?
答案 0 :(得分:3)
至少从C90开始,这种初始化是允许的。
来自C90 6.5.7“初始化”
具有静态存储持续时间的对象的初始值设定项中的所有表达式或具有聚合或联合类型的对象的初始化列表中的所有表达式都应为常量表达式。
和6.4“常量表达式”:
地址常量是指向左值的指针,该左值指定静态存储持续时间的对象,或指向函数指示符;它应该使用一元& amp;操作者...
但是,某些实现可能会对构造有问题 - 我猜这对于现代实现来说是不正确的。
答案 1 :(得分:2)
根据n1570 6.6第9段,函数的地址是地址常量,根据6.7.9,这意味着它可用于初始化全局变量。我几乎可以肯定这也是有效的C89。
<强>然而,强>
在理智的平台上,函数指针(或除NULL
之外的任何指针)的值仅在运行时才知道。这意味着结构的初始化不能在运行时进行。这并不总是适用于可执行文件,但它几乎总是适用于Python扩展等共享对象。我建议阅读Ulrich Drepper关于这个主题的论文(link)。
我不知道这是哪个平台,但如果Python开发人员提到它,几乎可以肯定,因为其中一个被它咬了。如果您真的很好奇,请尝试查看旧的Python扩展,看看提交日志中是否有相应的消息。
编辑:看起来大多数Python模块都是正常的,并静态初始化类型结构,例如static type obj = { function_ptr ... };
。例如,查看动态加载的mmap
模块。
答案 2 :(得分:1)
该示例最终符合C99,AFAIR也符合C89。
如果某个特定的(旧的)编译器出现问题,我认为所提出的解决方案不是最佳选择。不要对表现良好的平台强加动态初始化。相反,特殊情况需要特殊处理的怪物。并尝试尽可能快地逐步淘汰它们。