他の人が言ったように、これは C では不可能ですint
。3 つのタイプの中で最大のものは正しいですが、この事実の意味を見逃しているようです。
Cでこれが不可能なのはなぜですか?
C では、データはメタデータのオーバーヘッドなしでメモリに直接格納されます。変数は、メモリ内のデータに直接マップされます。作成しない限り(フラグがないという要件に違反するか、渡されるポインターのタイプを追跡する必要があります)、次のような変数に情報は保存されません。
- それはどのタイプですか
- 変数が初期化されているかどうか
- 変数がスコープ内にあるかどうか
- または (配列/文字列の場合) 使用される長さ、または使用可能なサイズ
他の言語にもあるように。代わりに、この情報は、この情報struct
を格納する を作成するか、何が起こっているかをプログラマーに覚えてもらうことにより、プログラマーが維持する必要があります。
C はシステム プログラミング言語であり、Java や C# のようなオーバーヘッドがないため、システム プログラミングに適しています。
わかりましたが、ユニオンでは機能しないのはなぜですか?
指しているタイプのさまざまなサイズの意味は何ですか? 次のメモリ ダイアグラムを検討してください。各文字は 4 ビット、int は 32 ビット、short は 16 ビット、char は 8 ビットです。
ニブル:89ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
[other ][data ][int ][int ][int ][mo][re][ ][da][ta] // Ints
[other ][data ][sh][or][t ][sh][or][t ][mo][re][ ][da][ta] // Shorts
[other ][data ][][][][][][][][][][][][][mo][re][ ][da][ta] // Chars
これはアライメントとエンディアンの問題を完全に無視していることに注意してください。いくつかのプラットフォーム (ARM を含む。これは、他の質問のいくつかで見られます) があり、あなたを助けることができるアライメントについて特定の保証が行われています.(†)
ただし、静的メモリまたはヒープ上のメモリにはまだ問題が残っています。文字配列に文字列を格納するとどうなるかを考えてみましょうABCDEFGHIJKL
。ASCIIA
が 0x41 であることを思い出すと、メモリ内では次のようになります。
[その他][データ]4142434445464748494A4B4C[も][れ][][だ][た]
C
これを整数として逆参照する関数にポインタを渡したとします。
[int ] // C への Int ポインター
[other ][data ][][][][][][][][][][][][][mo][re][ ][da][ta] // Chars
[その他][データ]4142434445464748494A4B4C[も][れ][][だ][た]
^-- C はここにあります。0x43
ここで int ポインターを使用すると、C 仕様に違反します。
それだけでは不十分で、コンパイラが論理的に動作すると仮定すると、ワード境界を越えてメモリを逆参照しようとし、バス フォールトまたは使用法フォールトをスローする可能性があります (ARMv7 で実際に何をするか忘れましたが、これらのフォールトのいずれかがプログラムを終了します)。
それでも十分ではなく、何らかの形で要求どおりに動作する場合、0x43 ではなく 0x43444546 の値を使用しているため、操作は間違った応答を生成します。
ARM プロセッサでのメモリ アラインメントに関するいくつかの脚注
(†) たとえば ARM では、ABI は通常の使用ではスタックをワード境界で整列する必要があると指定しています ( sp % 4 == 0
)。
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
[その他][データ][int][int][int][モ][レ][][ダ][タ]
[その他][データ][sh][or][t][sh][or][t][mo][re] ...
[その他][データ][][][][][][][][] ...
スタックは、パブリック インターフェイスに対してダブルワード アラインメントも保証されており、内部的に維持する必要はありません。詳細については、AAPCS の 5.2.1 を参照してください。それにもかかわらず、これはあなたが依存したいものではなく (ほとんどの場合、移植可能なコードが望ましいです)、コンパイラまたは生のアセンブリ コードを作成している場合を除き、知る必要さえありません。