CとC ++の列挙型ストレージの違い

ニルス・ピペンブリンク

C ++に移植するCプロジェクトで次の構造に出くわしました。

enum TestEnum 
{
    A=303,
    B=808
} _TestEnum;

int foo()
{
  _TestEnum = B;
}

GCCでコンパイルし、生成されたコードを見ると、次のようになります。

nils@doofnase ~ $ gcc -std=c90 -O2 -c ./test.c -o test.o
nils@doofnase ~ $ size test.o
   text    data     bss     dec     hex filename
     59       0       0      59      3b test.o

したがって、ゼロバイトのデータまたはBSSセグメントが使用されます。

一方、C ++でコンパイルすると、次のようになります。

nils@doofnase ~ $ g++ -std=c++11 -O2 -c ./test.c -o test.o
nils@doofnase ~ $ size test.o
   text    data     bss     dec     hex filename
     59       0       4      63      3f test.o

予想どおり、BSSに4バイトのストレージが割り当てられています。

また、Cプロジェクトでは、列挙型定義は実際には複数のcファイルに含まれるヘッダーファイルにあります。プロジェクトは正常にコンパイルおよびリンクされます。コンパイルしてC ++としてリンクすると、コンパイラは_TestEnumが複数のオブジェクトで定義されていると文句を言います(そうです!)。

ここで何が起こっているのですか?古風なC言語の特殊なケースを見ていますか?

編集:完全な目的のために、これはgccバージョンです:

nils@doofnase ~ $ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Grzegorz Szpetkowski

デフォルトでは、GCCコンパイラはC拡張を有効にします-pedanticフラグが有効な場合でも)。これにより、変換ユニット全体でオブジェクトの複数の外部定義が可能になります

C11(N1570)J.5.11を参照複数の外部定義(参考セクション):

キーワードの明示的な使用の有無にかかわらず、オブジェクトの識別子には複数の外部定義が存在する場合がありexternます。定義が一致しない場合、または複数が初期化されている場合、動作は未定義です(6.9.2)。

この動作に依存するアプリケーションは、ISOC言語に厳密に準拠していないことに注意してください。より具体的には、C11 6.9 / p5外部定義は次のように述べています(私の強調):

外部定義は、関数(インライン定義以外)またはオブジェクトの定義である外部宣言です。外部リンケージで宣言された識別子が式で使用される場合(結果が整数定数である演算子sizeofまたは_Alignof演算子のオペランドの一部として以外)、プログラム全体のどこかに、識別子の外部定義が1つだけ存在する必要があります。それ以外の場合は、1つしか存在しないものとします161)

技術的には、そのルールに違反すると、未定義の動作が発生します。つまり、実装が診断メッセージを発行する場合としない場合があります。

この拡張機能がnm次のコマンドで有効になっていることを確認できます。

nm test.o 
0000000000000000 T foo
0000000000000004 C _TestEnum

によるとman nm

「C」記号は一般的です。一般的なシンボルは初期化されていないデータです。リンクすると、複数の共通記号が同じ名前で表示される場合があります。シンボルがどこかに定義されている場合、共通のシンボルは未定義の参照として扱われます。

この拡張機能を無効にするには、-fno-commonフラグを使用できますGCCドキュメントから:

Unix Cコンパイラは、従来、共通ブロック内の初期化されていないグローバル変数にストレージを割り当ててきました。これにより、リンカは、異なるコンパイル単位内の同じ変数のすべての暫定定義を同じオブジェクトまたは非暫定定義に解決できます。これは、で指定された動作-fcommonであり、ほとんどのターゲットでのGCCのデフォルトです。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

列挙型と列挙型の違い

分類Dev

extern "C"とのC対C ++列挙型リンケージ

分類Dev

Typescriptの列挙型とオブジェクトの違いは何ですか

分類Dev

リストと列挙の違い

分類Dev

Typescriptの列挙型と定数の違い

分類Dev

Ada列挙型とC列挙型のインターフェース

分類Dev

C#辞書のキー/値配列/リストと互換性のない列挙可能な型

分類Dev

CとC ++の列挙型の範囲

分類Dev

JSONスキーマ列挙型と同等のC#クラス

分類Dev

列挙型ごとの異なる列挙型のグループリスト

分類Dev

C型とC ++型の違い(typedef)

分類Dev

カスタムトレイトとbool型のc ++ 11列挙型を使用する場合のclangでのコンパイルエラー

分類Dev

列挙型パラメーターのDefaultValueとRawDefaultValueの予期しない違い

分類Dev

列挙型構造体と列挙型クラスの違いは何ですか?

分類Dev

特定の列挙型にキャストされたC#ジェネリック列挙型

分類Dev

Java列挙型とプライベートコンストラクターを持つクラスの違いは何ですか?

分類Dev

任意の列挙型を取ることができるテンプレート(非型)パラメータークラスを作成できますか?C ++ 11

分類Dev

sprintf関数を使用した後の文字列のメモリとCの整数配列のストレージの違い

分類Dev

Java列挙とイテレータの違い

分類Dev

C ++でのスコープ外の列挙、列挙子、および基になる型のあいまいさ

分類Dev

テンプレートパラメータとして列挙型を使用してc ++のテンプレートクラスから継承

分類Dev

C#でジェネリックスと列挙型を使用して属性のリストを作成する

分類Dev

InnoDBと他のストレージエンジンの違い

分類Dev

C ++のカスタム値とコンストラクターを持つJavaタイプの列挙型

分類Dev

Kotlinのリスト型と配列型の違い

分類Dev

C ++ 17とC ++ 11の非型テンプレートパラメーターの違いは何ですか?

分類Dev

列挙型データを使用してオブジェクトのリストを作成するC#

分類Dev

Cで列挙型タグと変数名を宣言するための良いユースケース?

分類Dev

ペスターと列挙型のテスト

Related 関連記事

  1. 1

    列挙型と列挙型の違い

  2. 2

    extern "C"とのC対C ++列挙型リンケージ

  3. 3

    Typescriptの列挙型とオブジェクトの違いは何ですか

  4. 4

    リストと列挙の違い

  5. 5

    Typescriptの列挙型と定数の違い

  6. 6

    Ada列挙型とC列挙型のインターフェース

  7. 7

    C#辞書のキー/値配列/リストと互換性のない列挙可能な型

  8. 8

    CとC ++の列挙型の範囲

  9. 9

    JSONスキーマ列挙型と同等のC#クラス

  10. 10

    列挙型ごとの異なる列挙型のグループリスト

  11. 11

    C型とC ++型の違い(typedef)

  12. 12

    カスタムトレイトとbool型のc ++ 11列挙型を使用する場合のclangでのコンパイルエラー

  13. 13

    列挙型パラメーターのDefaultValueとRawDefaultValueの予期しない違い

  14. 14

    列挙型構造体と列挙型クラスの違いは何ですか?

  15. 15

    特定の列挙型にキャストされたC#ジェネリック列挙型

  16. 16

    Java列挙型とプライベートコンストラクターを持つクラスの違いは何ですか?

  17. 17

    任意の列挙型を取ることができるテンプレート(非型)パラメータークラスを作成できますか?C ++ 11

  18. 18

    sprintf関数を使用した後の文字列のメモリとCの整数配列のストレージの違い

  19. 19

    Java列挙とイテレータの違い

  20. 20

    C ++でのスコープ外の列挙、列挙子、および基になる型のあいまいさ

  21. 21

    テンプレートパラメータとして列挙型を使用してc ++のテンプレートクラスから継承

  22. 22

    C#でジェネリックスと列挙型を使用して属性のリストを作成する

  23. 23

    InnoDBと他のストレージエンジンの違い

  24. 24

    C ++のカスタム値とコンストラクターを持つJavaタイプの列挙型

  25. 25

    Kotlinのリスト型と配列型の違い

  26. 26

    C ++ 17とC ++ 11の非型テンプレートパラメーターの違いは何ですか?

  27. 27

    列挙型データを使用してオブジェクトのリストを作成するC#

  28. 28

    Cで列挙型タグと変数名を宣言するための良いユースケース?

  29. 29

    ペスターと列挙型のテスト

ホットタグ

アーカイブ