Can';是否使用另一个翻译单元的函数指针初始化静态结构?

Can';是否使用另一个翻译单元的函数指针初始化静态结构?,c,c99,c89,C,C99,C89,Python文档声称以下内容在“某些平台或编译器”上不起作用: 具体来说,Python文档说: 我们想把它分配给tp_的新插槽,但我们不能,因为 出于可移植性的考虑,在某些平台或编译器上,我们不能静态地 使用另一个C中定义的函数初始化结构成员 模块,因此,我们将在模块中分配tp_新插槽 在调用PyType_Ready()之前初始化函数-- 上述标准是否为C89和/或C99?哪些编译器特别不能处理上述问题?至少从C90开始,这种初始化就被允许了 从C90 6.5.7“初始化” 具有静态存储持续时间

Python文档声称以下内容在“某些平台或编译器”上不起作用:

具体来说,Python文档说:

我们想把它分配给tp_的新插槽,但我们不能,因为 出于可移植性的考虑,在某些平台或编译器上,我们不能静态地 使用另一个C中定义的函数初始化结构成员 模块,因此,我们将在模块中分配tp_新插槽 在调用PyType_Ready()之前初始化函数--


上述标准是否为C89和/或C99?哪些编译器特别不能处理上述问题?

至少从C90开始,这种初始化就被允许了

从C90 6.5.7“初始化”

具有静态存储持续时间的对象的初始值设定项或具有聚合或联合类型的对象的初始值设定项列表中的所有表达式都应为常量表达式

和6.4“常量表达式”:

地址常量是指向指定静态存储持续时间对象的左值的指针,或指向函数指示符的指针;应使用一元运算符和运算符显式创建它


但是,某些实现可能会在构造上遇到问题,我想这对于现代实现来说是不正确的。

根据n1570 6.6第9段,函数的地址是地址常量,根据6.7.9,这意味着它可以用来初始化全局变量。我几乎可以肯定这也是有效的C89

但是,

在sane平台上,函数指针(或除
NULL
以外的任何指针)的值仅在运行时已知。这意味着在运行时之前不能对结构进行初始化。这并不总是适用于可执行文件,但它几乎总是适用于诸如Python扩展之类的共享对象。我建议你读一下乌尔里希·德雷珀关于这个问题的文章()

我不知道这是在哪个平台上打破的,但是如果Python开发人员提到它,几乎可以肯定是因为其中一个被它咬了。如果您真的很好奇,请尝试查看一个旧的Python扩展,看看提交日志中是否有适当的消息


Edit:看起来大多数Python模块只是做普通的事情,静态地初始化类型结构,例如,
静态类型obj={function\u ptr…}。例如,查看动态加载的
mmap
模块。

该示例完全符合C99,AFAIR也符合C89


如果某个特定的(老式的)编译器对此有问题,我不认为建议的解决方案是可行的。不要将动态初始化强加给表现良好的平台。相反,特例是需要特殊治疗的怪人。并尽可能快地逐步淘汰它们

N1570是即将推出的C201x标准的最新(?)草案。它还没有官方身份,也没有人实现它描述的语言,最新的C99草案(包括标准和三个技术勘误)在大多数情况下更有用。@Keith:我只是指目前最方便的版本。没有C编译器不能处理它(任何这样的编译器都不是C编译器),但正如Dietrich指出的,它可能会带来额外的运行时成本(搬迁)并且可能会阻止结构存储在只读段中,即使它声明为
const
@R。但是对于“初始化函数”中可能发生的任何情况,这些都是正确的。因此使用静态初始化不会造成任何潜在的额外伤害,对吗?@Michael:的确如此。我认为Python的文档亚当:我的标准副本确实有第6.4节。这是“ANSI/ISO 9899-1990”标准。我的理解是,章节的编号从ANSI第一次发布该标准时更改为成为ISO标准时。或者类似的(因此编号与互联网上提供的最终草案ANSI C89 ASCII文本文档不匹配)。
int foo(int);  // Defined in another translation unit.
struct X { int (*fptr)(int); } x = {&foo};