93047


名前の無い構造体を使用した`inline struct { int x; }
y;`というインライン変数が、翻訳単位毎に別の実体(アドレスも別)となり、翻訳単位を越えて共有できません。  
なぜ異なる実体になってしまうのでしょうか。

**a.cpp**

[code]

    #include <cstdio>
    
    // NG
    inline struct { int x; } y;
    // OK
    inline int x;
    inline struct S { int x; } z;
    
    void b();
    
    int main()
    {
        b();
    
        // NG
        printf("main: %d\n", ++y.x);
        // OK
        printf("main: %d\n", ++x);
        printf("main: %d\n", ++z.x);
    }
    
[/code]

**b.cpp**

[code]

    #include <cstdio>
    
    // NG
    inline struct { int x; } y;
    // OK
    inline int x;
    inline struct S { int x; } z;
    
    void b()
    {
        printf("b: %d\n", ++y.x);
        printf("b: %d\n", ++x);
        printf("b: %d\n", ++z.x);
    }
    
[/code]

[code]

    $ clang++ a.cpp b.cpp -Wall -Wextra -std=c++17
    
[/code]

**[実行結果](https://wandbox.org/permlink/A5e1Pe4dOnkWMg16)**

[code]

    b: 1
    b: 1
    b: 1
    main: 1
    main: 2
    main: 2
    
[/code]

試した環境:

  * clang 15(-std=c++17)
  * gcc 12(-std=c++17)


CC BY-SA 4.0
2022-12-27T12:26:11.800
93046
2022-12-28T01:07:49.277
9113
question
c++
インライン変数が翻訳単位毎に別々の実体となってしまう


名前の無い構造体は外部リンケージを持たない。  
そのため翻訳単位が異なると別の実体と見なされる。

英語版の回答より:  
[c++ - Why does an unnamed struct inline variable not have the same address in
every translation unit? - Stack
Overflow](https://stackoverflow.com/questions/62670987/why-does-an-unnamed-
struct-inline-variable-not-have-the-same-address-in-every-tr)

>
> インライン指定子をちょっとだけ無視してみましょう。インライン指定子がなかったと想像してみよう。あなたのコードはまだ同じ結果を生むだろう。その理由は、クラス型自体のリンケージにある。
>

>> [basic.link]

>>

>> [8](https://timsong-cpp.github.io/cppwp/n4659/basic.link#8).
ある型がリンケージを持つとされるのは、以下の場合のみです。

>>

>>   * 名前が付けられている（またはリンケージ目的の名前（[dcl.typedef]）がある）クラスまたは列挙型で、その名前にリンケージがある場合。

>>   * リンケージを持つクラスのメンバである無名クラスまたは無名列挙型である場合、または

>>   * クラステンプレート（条項 [temp]）35の特殊化である。

>>   * 基本型である。

>>   * リンケージを持つ型のみから構成される，クラスや列挙以外の複合型である．

>>   * リンケージを持つ型のcv修飾バージョンである。

>>

>>

>> リンケージを持たない型は，次の場合を除いて，外部連結を持つ変数又は関数の型として使用してはならない。

>>

>>   * 実体がC言語のリンケージを持つ場合。

>>   * 実体が無名名前空間内で宣言されている場合、または

>>   * 実体がodr-usedでない、または同じ翻訳単位で定義されている場合。

>>

>>

>>
[注：言い換えれば、リンケージのない型は、その翻訳単位の外側で名前を付けられないクラスまたは列挙を含む。このような型を使用して宣言された外部リンケージを持つ実体は、プログラムの他の翻訳単位の他の実体に対応することができないので、odr-
usedであれば翻訳ユニットで定義されなければならない。また、リンケージをもつクラスは、リンケージをもたない型をもつメンバを含むことができ、型がリンケージをもつかどうかの判断には、typedef名は無視されることに注意すること。]

>
> ご覧の通り、使用するクラス型にはリンクがありません。つまり、引用したパラグラフでは、（外部リンクのある）変数をodr-
> useしているので、コードが適格であるためには、それが使われるのと同じ翻訳単位で定義されなければならないのです。つまり、そのヘッダーを含む異なる翻訳単位で異なる定義がなされることになります。
>
>
> 結局のところ、インライン指定があってもなくても、これらの定義が同じオブジェクトのものであることはありえません。そのため、最終的には異なるアドレスが表示されることになります。


CC BY-SA 4.0
2022-12-27T12:26:11.800
93047
2022-12-28T01:07:49.277
2022-12-28T01:07:49.277
9113
9113
93046
answer