无法使用另一个翻译单元的函数指针初始化静态结构?
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?哪些编译器具体不能处理上述内容?
The Python documentation claims that the following does not work on "some platforms or compilers":
int foo(int); // Defined in another translation unit.
struct X { int (*fptr)(int); } x = {&foo};
Specifically, the Python docs say:
We’d like to just assign this to the tp_new slot, but we can’t, for
portability sake, On some platforms or compilers, we can’t statically
initialize a structure member with a function defined in another C
module, so, instead, we’ll assign the tp_new slot in the module
initialization function just before calling PyType_Ready(). --http://docs.python.org/extending/newtypes.html
Is the above standard C89 and/or C99? What compilers specifically cannot handle the above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
至少从 C90 起就允许这种初始化。
来自 C90 6.5.7“初始化”
和 6.4“常量表达式”:
但是某些实现肯定可能在构造上遇到问题 - 我猜这对于现代实现来说并非如此。
That kind of initialization has been permitted since at least C90.
From C90 6.5.7 "Initialization"
And 6.4 "Constant expressions":
But it's certainly possible that some implementations might have trouble with the construct - I'd guess that wouldn't be true for modern implementations.
根据n1570 6.6第9段,函数的地址是一个地址常量,根据6.7.9这意味着它可以用来初始化全局变量。我几乎可以肯定这也是有效的 C89。
但是,
在正常的平台上,函数指针(或除
NULL
之外的任何指针)的值仅在运行时才知道。这意味着结构的初始化要到运行时才能进行。这并不总是适用于可执行文件,但它几乎总是适用于共享对象,例如 Python 扩展。我建议阅读 Ulrich Drepper 关于该主题的文章(链接)。我不知道这个问题在哪些平台上出现,但如果 Python 开发人员提到它,几乎可以肯定是因为其中一个人被它咬了。如果您真的很好奇,请尝试查看旧的 Python 扩展并查看提交日志中是否有适当的消息。
编辑:看起来大多数Python模块只是做正常的事情并静态初始化类型结构,例如
static type obj = { function_ptr ... };
。例如,看看mmap
模块,它是动态加载的。According to n1570 6.6 paragraph 9, the address of a function is an address constant, according to 6.7.9 this means that it can be used to initialize global variables. I am almost certain this is also valid C89.
However,
On sane platforms, the value of a function pointer (or any pointer, other than
NULL
) is only known at runtime. This means that the initialization of your structure can't take place until runtime. This doesn't always apply to executables but it almost always applies to shared objects such as Python extensions. I recommend reading Ulrich Drepper's essay on the subject (link).I am not aware of which platforms this is broken on, but if the Python developers mention it, it's almost certainly because one of them got bitten by it. If you're really curious, try looking at an old Python extension and seeing if there's an appropriate message in the commit logs.
Edit: It looks like most Python modules just do the normal thing and initialize type structures statically, e.g.,
static type obj = { function_ptr ... };
. For example, look at themmap
module, which is loaded dynamically.该示例明确符合 C99,AFAIR 也符合 C89。
如果某个特定的(旧的)编译器有问题,我不认为建议的解决方案是可行的方法。不要对表现良好的平台强加动态初始化。相反,特殊情况需要特殊对待的怪人。并尝试尽快逐步淘汰它们。
The example is definitively conforming to C99, and AFAIR also C89.
If some particular (oldish) compiler has a problem with it, I don't think that the proposed solution is the way to go. Don't impose dynamic initialization to platforms that behave well. Instead, special case the weirdos that need special treatment. And try to phase them out as quickly as you may.