2016-09-08 19 views
1

考えてみましょう私は2つの符号なしの数値をそれぞれ32ビットで1つの配列に保存しました。最初の数字は位置[0; 3]、第2の位置[4; 8]。私は今、数字の1つの値を変更するために、次のコードが許されているか問題がありますか?uint32_t *を使用してuint8_t配列の値を変更する

uint8_t array[8]; 
//...Fill it up... 

uint32_t *ptr = NULL; 
ptr = (uint32_t*)&array[0]; 
*ptr = 12345; 

ptr = (uint32_t*)&array[4]; 
*ptr = 54321; 
+5

はい、それは問題があります、http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule –

+2

有効なタイプ(別名厳密なエイリアシング)ルールに違反しています。これは明確な**です**マーシャリングを使用するビットシフト/マスキングを使って配列を読み取ることができます – Olaf

+1

あなたは 'uint32_t'値でいっぱいになる' uint32_t'の配列を持っています: 'uint8_t *'( "あなたが気にしない限りデータ表現)。 –

答えて

1

あなたはuint32_tへのポインタでuint8_t配列にアクセスすることはできません。それはthe strict aliasing ruleの違反です(他の方法ではOK - uint8_tが文字タイプの場合)。

代わりに、あなたがC(上記C99と)型システムを回避するために、「type punning"を使用する場合がありますそのため、あなたはそれぞれの種類のメンバーとunionを使用します。

union TypePunning { 
    uint32_t the_ints[2]; 
    uint8_t the_bytes[2 * sizeof(uint32_t)]; 
} 
// now e.g. write to the_bytes[1] and see the effect in the_ints[0]. 
// Beware of system endianness, though! 
+0

'uint8_t'は文字型ではありません!常に符号なし整数型です。そして、他の方法はOKではありません。 6.5p6、最初の文章を参照してください! UBを呼び出さない一方で、組合アプローチにも問題があります。 – Olaf

+0

@Olaf、 'uint8_t'は整数型で、' char'はそうではありません。この標準には、「文字の種類」というより広いカテゴリはありません。特に、 'signed char'と' unsigned char'はそのようなカテゴリを形成する 'char'とグループ化されません;符号付き/符号なし型は整数型の間でグループ化されます。 –

+0

@JohnBollinger:6.2.5p6、最後の文章: "...標準と拡張の符号なし整数型は集合的に_unsigned整数型と呼ばれます_"。 'uint8_t'は、標準の符号なし整数型_である' unsigned char'以外のものであってはなりません。 – Olaf

関連する問題