微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C 11链接上的调用寄存器功能?

有没有办法通过链接其.o文件调用函数

例如:

Foo.cpp中:

extern int x;

void f() { x = 42; }

struct T { T() { f(); } } t; // we use constructor of global
                             // object to call f during initialization

bar.cpp:

#include <iostream>

int x;

int main()
{
    std::cout << x;
}

要编译/链接/运行:

$g++ -c foo.cpp
$g++ -c bar.cpp
$g++ foo.o bar.o
$./a.out
42

这似乎与gcc 4.7一起使用.它按预期输出42.但是我记得一些旧的编译器,我有一个这个模式的问题,因为没有什么是真正的“使用”foo.o它被优化在链接时间. (也许这个特定的例子不是由于某种原因代表问题)

C11标准对这种模式有什么看法?保证工作吗?

解决方法

我相信你没有脱钩.该标准不能保证您的代码按照预期的方式工作,尽管许多人依赖这种行为进行各种“自我注册”的构造.

您的对象t被动态初始化,这具有调用f的副作用.这个标准有关静态存储对象的动态初始化的说明(3.6.2 / 4,“非局部变量的初始化”):

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage
duration is done before the first statement of main. If the initialization is deferred to some point in time
after the first statement of main,it shall occur before the first odr-use (3.2) of any function or variable
defined in the same translation unit as the variable to be initialized.

在你的代码中,只有x是odr使用的,但是x在主要的翻译单元中定义.程序中没有使用其他TU的变量或函数,所以在技术上不能保证t将被初始化.从技术上讲,每个TU的内容必须由程序的静态控制流程引用,以便初始化所有内容.

正如我所说,有很多真实世界的代码,有“自我注册”翻译单位(例如,在字符串键映射中注册一个工厂函数指针),以便通过简单地添加TU到最终的程序,你结束具有更多的功能.我被告知大多数编译器将无条件地初始化所有全局变量,因为不这样做会打破很多现实世界的代码.但不要依赖它!

原文地址:https://www.jb51.cc/c/113022.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐