2017-12-24 21 views
4

このコードを検討してください。パディングの存在が保証されています。これらstatic_assert sの構造体または共用体のパディングにアクセスすることは安全ですか?

static_assert(_Alignof(char) < _Alignof(double), "Flip!"); 
static_assert(sizeof(char) < sizeof(double), "Flop!"); 

struct S { 
    char c[1]; 
    double d; 
}; 
union U { 
    char c[1]; 
    double d; 
}; 

static_assert(sizeof(struct S) == _Alignof(double) * sizeof(double), "Fudge!"); 
static_assert(sizeof(union U) == sizeof(double), "Futz!"); 

S s; U u; 
s.c[1] = 0; // What? 
u.c[1] = 0; // What? 

、それはパディングが途中または末尾にありますのは間違いないだろう。それらにアクセスすることは安全ですか?

+5

これはUBです。可能であれば、コンパイラはデバッグビルドの配列のバインドチェックを行うことができるため、UBです。 punnig型に関しては、次のような疑問があります。[C99で型宣言されていないユニオンを使って、C11で指定されていますか? 質問](https://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified) – Ivan

+1

alligbnmentはあまりない隣接フィールドのために通常は検出されない配列をオーバーロードすることになりますが、 'c [1]'はエラーです –

+3

パディングに確実にアクセスすることはできません。構造体(共用体)割り当ての下でコピーされるパディングに頼ることはできません。そこにはバイトがあるという意味でそれらにアクセスすることは "安全"です。彼らと一緒にできることは何も意味がなく信頼できるものではありません。このようなバイトを使用する場合は、明示的に 'struct S2 {char c [1];ショートs; int i;ダブルd; } '(32ビットIntel x86を除くほとんどのシステムでは、' struct S'と同じサイズになります)。私はあなたの最初の静的なアサーションは32ビットx86で発生すると信じています。 –

答えて

0

パディングビットが含まれていても、memcpy()、、またはその他の類似の構造全体が安全です。しかし、その値を保持しているパディングについては仮定することはできません。

したがって、パディングビットにアクセスする唯一の用途は、状況に応じてコードへのアクセスを避けるためにコードを書く必要がないことです。

memcmp()のような操作では、結果が予測できないため、パディングビットにアクセスするのは依然として間違いです。

関連する問題