ベストアンサー
マシンの境界やネットワークプロトコル全体で構造オフセットを一致させる必要がある場合、非常に厄介な難問です。 。仕様によると、サイズは、取得できる最大値を表すために必要な最小値でなければなりません。したがって、たとえば、一般的なステートマシンの状態列挙型は1バイトしか必要としない場合があります。
AFAIKにはサイズを制御する方法が3つしかありません。
一部の(すべてではない)コンパイラにはサイズをsizeof(int)または32ビットのいずれかに強制するコンパイラスイッチ。スイッチの構文は、たとえばMSCとgccc / clangの間で同じではありません。
2番目の方法は、たとえば16ビットフィールドに入力する必要がある場合、そのサイズを必要とするダミーの最大値を定義することです。
もう1つの方法は、構造体定義で通常のintスタイルを使用することですが、列挙型名で値を表示するというデバッガーの利便性を放棄し、代わりに整数のみを取得します。
次に、列挙型を含む構造体がパックされ、パディングされていないことを指定する必要があります。
回答
変数の一部がない場合x
はconst
またはvolatile
であり、x
は配列型ではありません。次に、ステートメント…
x = x;
…ほとんど何もしません。整形式です。x
が事前に初期化されていると仮定すると¹、も明確に定義されています。割り当てはいくつかの潜在的な例外を除いて、プログラムの状態を実際に変更します(以下を参照)。
これは、x
にタイプ。
struct foo {
char buf[42];
int x;
};
struct foo x = { "Hello World", 18 };
x = x; // no big deal.
では、「間違い」とは何ですか? 便利なコードではありませんが、その説明に当てはまるコードはかなりたくさんあります。何か他のことをしようとして失敗した場合、それは間違いにすぎません。
[補遺:この割り当てが役に立たないことを考えると、コンパイラは 警告する傾向があります。あなたがしたは別の意味です。]
const
と?const
の制限は単純です。つまり、「読み取り専用」を意味するため、「書き込むことはできません」。少なくとも、単純な割り当てではありません。
volatile
に関するものは注意が必要です。そのキーワードは、それによって修飾された値が実装に見えない方法で変更される可能性があり、それに書き込むと副作用が生じる可能性があることを示しています。ここでラットホールを掘り下げることなく、実際には、揮発性オブジェクトに対して実行できる、合理的に明確に定義された操作は次のようになります。
volatile int v;
int i;
i = v; // reads from v once, places into i.
v = i; // writes to v once with the contents of i.
volatile
を使用すると、それよりも少し多くのことができます。しかし、ほんのわずかです。これは別の日のトピックです。C++ 20がvolatile
の一部の使用を除いてすべて非推奨にした理由があります。それらの変更は非常に賢明に見えます。
上記で考えられるいくつかの例外について説明しました。 Jonas Oberhauserは、struct
のパディングは必ずしもその割り当てによって保持されるとは限らないことを思い出しました。
また、理論的には、同じ値を複数の方法で表すことができる場合、割り当てによってオブジェクトの基底表現が変更される可能性があります。
うまくいけば、あなたのプログラムは両方の可能性に鈍感です。ただし、オブジェクトの基になる 表現を見ると、違いがわかります。たとえば、memcmp
などの関数が気付く場合があります。同様に、 タイプのパンニングを使用する場合。
¹そうでない場合は、 未定義の動作へようこそ。 おそらく、次のいずれかに違反しているためです。