为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
Why does an unnamed struct inline variable not have the same address in every translation unit?
thing.hpp
:
struct
{
} inline thing;
other.cpp
:
#include "thing.hpp"
#include <cstdio>
void test()
{
std::printf("test: %pn", &thing);
}
main.cpp
:
#include "thing.hpp"
#include <cstdio>
extern void test();
int main()
{
std::printf("main: %pn", &thing);
test();
}
在 C++17 模式下使用 Clang 11 或 GCC 9.3.0 编译时,输出如下所示:
main: 0x404031
test: 0x404032
根据我的理解,具有相同定义的内联变量在每个翻译单元中都应该具有相同的地址.
给结构类型命名会导致地址相同。
为什么thing
在不同的翻译单元中没有相同的地址?
让我们暂时忽略内联说明符。想象一下它缺席了。您的代码仍会产生相同的结果。原因是类类型本身的链接。
[basic.link]
8 当且仅当以下情况下,称为类型具有链接:
- 它是命名的类或枚举类型(或具有用于链接目的的名称 ([dcl.typedef]((,并且该名称具有链接;或
它是一个未命名的类或- 未命名的枚举,它是具有链接的类的成员;或
- 它是类模板(子句 [temp](35 的专用化;或
- 它是一种基本类型;或
它是类或- 枚举以外的复合类型,仅从具有链接的类型复合;或
- 它是具有链接的类型的 CV 合格版本。
没有链接的类型不得用作变量的类型或变量的类型 与外部链接功能,除非
- 实体具有 C 语言链接,或
- 实体在未命名的命名空间中声明,或者
- 实体未使用 ODR 或在同一转换单元中定义。
[ 注意:换句话说,没有链接的类型包含一个类或 不能在其翻译单元之外命名的枚举。一 使用此类类型声明具有外部链接的实体不能 对应于另一个翻译单元中的任何其他实体 程序,因此必须在翻译单元中定义,如果是 ODR 使用。另请注意,具有链接的类可能包含成员 其类型没有链接,并且 typedef 名称在 确定类型是否具有链接。 — 尾注 ]
如您所见,您使用的类类型没有链接。因此,在引用的段落下,由于您 odr-use 变量(具有外部链接(,因此必须在用于代码格式正确的同一翻译单元中定义它。这转化为包含该标头的不同翻译单元中的不同定义。
最终,无论是否使用内联说明符,这些定义都不能用于同一对象。所以你最终会看到不同的地址。
相关文章:
- 将数组的地址分配给变量并删除
- 什么时候调用组成单元对象的析构函数
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 不同翻译单元中不可重载的非内联函数定义
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 被解释为低级别const的const对象的地址
- 将地址分配给本地指针后,公共对象的变量将消失
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- 内联程序集printf将整数解释为地址
- 为什么指针不写入类的地址?
- 为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
- 当我使用需要计算数组单元格地址的模板时,奇怪的C++行为
- 外部内联函数在所有翻译单元中必须具有相同的地址.这到底是怎么实现的?
- 跨编译单元的相同函数模板实例化的地址
- 代码块:单元测试文件需要文件的整个地址