标准 C++ 库链接

2023-12-31

我试图了解标准库何时链接到我自己的二进制文件。我写了以下内容:

#include <stdio.h>

double atof(const char*);

int main(){
    const char * v="22";
    printf("Cast result is %f", atof(v));
}

编译成功g++ -c main.cpp,但是当我链接刚刚创建的目标文件时,出现错误。错误描述为:

/tmp/ccWOPOS0.o: In function `main':
main.cpp:(.text+0x19): undefined reference to `atof(char const*)'
collect2: error: ld returned 1 exit status

但我不明白为什么会出现这个错误?我认为标准 c++ 库自动链接到我的二进制文件ld链接器。包含头文件和仅声明我需要显式使用的函数之间有什么区别。


作为 C++ 中的一般规则,手动声明库函数(例如atof().

它曾经在旧的 C 程序中很常见,但 C 没有函数重载,因此它对“几乎”正确的声明更加宽容。 (好吧,有些旧的编译器是,我不能真正代表最新的编译器)。这就是为什么我们将 C 描述为“弱类型”语言,而 C++ 是一种更“强类型”的语言。

另一个复杂之处是编译器执行“名称修改”:它们传递给链接器的名称是源名称的修改版本。 C 编译器执行的名称修改可能与 C++ 编译器完全不同。标准库版本atof()是一个C函数。要在 C++ 源文件中声明它,您需要将其声明为

extern "C"
{
    double atof(const char *);
}

或者可能

extern "C" double atof(const char *);

还有许多额外的复杂性,但这足以继续下去。

最安全的想法是只包含适当的标头。

#include <iostream>
#include <cstdlib>

int main()
{
    const char v[]= "22";
    std::cout << "Cast result is " << atof(v) << std::endl;
    return 0;
}

回应 @DmitryFucintv 评论的额外背景

  1. 调用约定

当调用函数时,调用约定 http://en.wikipedia.org/wiki/Calling_convention是关于如何在调用函数和被调用函数之间传递参数和返回值的协议。在 x86 架构上,最常见的两个是__cdecl http://msdn.microsoft.com/en-us/library/zkwh89ks.aspx and __stdcall http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx,但还存在许多其他的。

考虑以下:

/* -- f.c --*/

int __stdcall f(int a, double b, char *c)
{
    // do stuff
    return something;
}

/* main.c */

#include <iostream>
extern int __cdecl f(int a, double b, char *c);

int main()
{
    std::cout << f(1, 2.3, "45678") << std::endl;
    return 0;
}

在 C 程序中,这可能会编译和链接正常。功能f()期望其参数为 __stdcall 格式,但我们以 __cdecl 格式传递它们。结果是不确定的,但很容易导致堆栈损坏。

因为 C++ 链接器有点复杂,所以它可能会生成像您看到的那样的错误。大多数人都会同意这是一个更好的结果。

2 名称修改

名称修改 http://en.wikipedia.org/wiki/Name_mangling(或名称装饰)是编译器向object名称给链接器一些提示。一个object可能是一个函数或一个变量。允许函数重载的语言(如 C++ 和 Java)必须执行类似的操作,以便链接器能够区分同名的不同函数之间的区别。 例如

int f(int a);
int f(double a);
int f(const char *a, ...);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

标准 C++ 库链接 的相关文章

  • 以相反的顺序迭代可变参数模板参数

    如果我手动反转传递给它的模板参数的顺序 以下代码将起作用 template
  • SL4 AutoCompleteBox 重复筛选结果问题

    我在 AutoCompleteBox 过滤方面遇到问题 它似乎记住了之前的过滤器 例如 我输入 A 它会返回 1 项 我删除 A 并输入 Z 这应该返回 1 项 问题是它返回 A 过滤器加上 Z 的结果 我删除 Z 并输入 S 这会带回 2
  • MVC 重定向到没有控制器的视图

    希望应该是一个简单的 我创建了一个通用错误视图 当整个站点的操作方法内发生异常时 我想显示该视图 我创建了一个部分页面 所有导航都位于其中 因此我不需要在此视图上使用控制器 那么如何从控制器内的操作方法重定向到它 像这样的东西 HttpPo
  • 没有 Unicode 字节顺序标记。无法切换到 Unicode

    我正在使用 XSD 编写 XML 验证器 下面是我所做的 但是当验证器到达该线时while list Read 它给了我错误 没有 Unicode 字节顺序标记 无法切换到 Unicode 有人可以帮我解决吗 public class Va
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • Android NDK C++“wstring”支持

    我有用 C 编写的源代码 lib 现在我想在 Android NDK 项目 NDK 6 中编译并使用相同的源代码 lib 我能够编译大多数 C 文件 除了基于 std wstring 的功能 在 Application mk 中 当我指定时
  • 如何将字节块读入结构体

    我有一个需要处理的资源文件 它包含一组文件 首先 资源文件列出了其中包含的所有文件 以及一些其他数据 例如在此结构中 struct FileEntry byte Value1 char Filename 12 byte Value2 byt
  • 使用 openssl 检查服务器安全协议

    我有一个框架应用程序 它根据使用方式连接到不同的服务器 对于 https 连接 使用 openssl 我的问题是 我需要知道我连接的服务器是否使用 SSL 还是 TLS 以便我可以创建正确的 SSL 上下文 目前 如果我使用错误的上下文尝试
  • QThread - 使用槽 quit() 退出线程

    我想在线程完成运行时通知对象 但是 我无法让线程正确退出 我有以下代码 处理器 cpp thread new QThread tw new ThreadWorker connect tw SIGNAL updateStatus QStrin
  • 数据损坏 C++ 和 Python 之间的管道

    我正在编写一些代码 从 Python 获取二进制数据 将其通过管道传输到 C 对数据进行一些处理 在本例中计算互信息度量 然后将结果通过管道传输回 Python 在测试时 我发现如果我发送的数据是一组尺寸小于 1500 X 1500 的 2
  • 更改其他页面的主窗口内容

    在 WPF 应用程序的主窗口中 我有一个 Badged 元素 来自材料设计 这是我的代码
  • 从包含大量文件的目录中检索文件

    我的目录包含近 14 000 000 个 wav 格式的音频样本 所有普通存储 没有子目录 我想循环浏览文件 但是当我使用DirectoryInfo GetFiles 在该文件夹上 整个应用程序冻结了几分钟 可以用另一种方式完成吗 也许读取
  • 如何不在类中实现接口的功能?

    面试时面试官问了我以下问题 但我不知道这个问题的答案是什么 请帮忙 如果我不想 我必须做什么 在我的类中实现一个函数 在接口中声明为 由我班实施 Edited 我正在使用 NET 和 C 如果有人可以提供 C 示例代码示例 那就太好了 Th
  • 是什么原因导致 Linq 错误:此方法无法转换为存储表达式?

    我有一堆具有相同 select 语句的 Linq to Entity 方法 所以我想我会很聪明 并将其分离到它自己的方法中以减少冗余 但是当我尝试运行代码时 我得到了以下内容错误 该方法不能转化为 商店表达式 这是我创建的方法 public
  • 无法通过 LINQ to Entities 使用某些功能?

    我正在尝试使用 LINQ 查询在项目上实现搜索功能 由于数据有时包含带有重音符号和其他符号的字符 因此我创建了一种方法来删除这些字符以进行搜索 这是我的代码 var addresses from a in db Addresses join
  • 将 bignum 类型结构转换为人类可读字符串的有效方法是什么?

    我有一点问题 为了增长我的 C 知识 我决定尝试实现一个基本的 bigint 库 bigint 结构的核心将是一个 32 位整数数组 选择它们是因为它们适合寄存器 这将允许我在数字之间进行操作 这些操作将在 64 位整数中溢出 这也将适合寄
  • 展开路径中具有环境变量的文件名

    最好的扩张方式是什么 MyPath filename txt to home user filename txt or MyPath filename txt to c Documents and settings user filenam
  • 为什么 C# 接口名称前面加上“I”

    这种命名约定背后的基本原理是什么 我没有看到任何好处 额外的前缀只会污染 API 我的想法与康拉德一致response https stackoverflow com a 222502 9898与此相关的question https sta
  • 如何使用 ASP.NET Web 表单从代码隐藏中访问更新面板内的文本框、标签

    我在更新面板中定义了一些控件 它们绑定到中继器控件 我需要根据匿名字段隐藏和显示用户名和国家 地区 但问题是我无法以编程方式访问更新面板中定义的控件 我如何访问这些控件 我也在网上查找但找不到很多参考资料 下面是来自aspx页面和 cs页面
  • 程序退出后,TcpListener Socket 仍处于活动状态

    当我的程序退出时 我试图停止 TCP 侦听器 我不关心套接字或任何活动客户端套接字上当前活动的任何数据 套接字清理代码本质上是 try myServer Server Shutdown SocketShutdown Both catch E

随机推荐