代码之家  ›  专栏  ›  技术社区  ›  tambre Serhii

为什么一个未命名的结构内联变量在每个翻译单元中的地址都不相同?

  •  1
  • tambre Serhii  · 技术社区  · 4 年前

    thing.hpp :

    struct
    {
    } inline thing;
    

    other.cpp :

    #include "thing.hpp"
    #include <cstdio>
    
    void test()
    {
        std::printf("test: %p\n", &thing);
    }
    

    main.cpp :

    #include "thing.hpp"
    #include <cstdio>
    
    extern void test();
    
    int main()
    {
        std::printf("main: %p\n", &thing);
        test();
    }
    

    用CLAN 11或GCC 93.0编译C++ 17模式,输出类似于此:

    main: 0x404031
    test: 0x404032
    

    根据我的理解,具有相同定义的内联变量在每个翻译单元中应该具有相同的地址。
    给结构类型一个名称会导致地址相同。

    为什么会这样 thing

    0 回复  |  直到 4 年前
        1
  •  3
  •   StoryTeller - Unslander Monica    4 年前

    让我们暂时忽略内联说明符。想象一下它不存在。您的代码仍然会产生相同的结果。原因是类类型本身的链接。

    [基本链接]

    8

    • 它是一个被命名的类或枚举类型(或具有用于链接目的的名称)([dcl.typedef类型定义]))且该名称具有联系;或
    • 作为具有链接的类的成员的未命名类或未命名枚举;或
    • 它是类模板(子句[temp])35的专门化;或
    • 它是类或枚举以外的复合类型,专门由具有链接的类型复合而成;或
    • 它是具有链接的类型的cv限定版本。

    具有外部联动功能,除非

    • 实体具有C语言链接,或
    • 实体在未命名的命名空间中声明,或者
    • 实体未使用odr或在同一翻译单元中定义。

    [注:换句话说,没有链接的类型包含一个类或 不能在其转换单元之外命名的枚举。安 无法使用此类类型声明具有外部链接的实体 因此必须在翻译单元中定义 使用odr。还要注意,具有链接的类可能包含成员 确定一个类型是否有连接。[尾注]

    如您所见,您使用的类类型没有链接。所以在引用的段落中,因为您使用了变量(具有外部链接),所以必须在相同的翻译单元中定义它,以便代码格式良好。它在不同的翻译单位中转换为不同的定义,包括该标题。

    最终,无论是否使用内联说明符,这些定义都不能用于同一个对象。所以你会看到不同的地址。