2016-07-01 9 views
2

厳密なエイリアシング警告を取り除く最も簡単な方法はどれですか?c - 厳密なエイリアシング警告の処理方法

コードは:

uint8_t msg[3]; 
int retval; 

msg[0] = (uint8_t) INT_READ_EVENT; 
*((uint16_t *) &msg[1]) = bytesToRead; 

retval = write(intPipe[1], msg, sizeof(msg)); 

bytesToReadはuint16_t値として渡されます。

一方、残りのデータが処理される前に、イベントタイプ(この場合はINT_READ_EVENT)を認識するために1バイトを受け取る読み取りがあります。

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
    *((uint16_t *) &msg[1]) = bytesToRead; 
    ^

警告を取り除くためにどの素早く、簡単な方法はありますか?

+1

エンディアンはどうですか?移植性のあるコードが必要ないのは確かですか?ビットシフトの使用を検討してください。 – Lundin

+0

@Lundinもし私が間違っているなら私を訂正しますが、私は本当にエンディアンを気にしますか?私はちょうどそれをuint16_tとして送信し、後でuint16_tの値として受け取りたい。値が内部的にどのように格納されるかは重要ですか? – Messut

+1

送信側コンピュータにはエンディアンがあり、実際のプロトコルにはエンディアンがあり、受信側にはエンディアンが設定されます。 3つのうちの1つが異なるエンディアンを使用する場合は、気にする必要があります。 – Lundin

答えて

1

charバッファを使用する代わりに、構造体を定義することができます。

struct message 
{ 
    uint8_t code; 
    uint16_t payload; 
}; 

struct message msg; 

msg.code = INT_READ_EVENT; 
msg.value = bytesToRead; 

マルチプラットフォーム/ポータブルコードでは、アラインメントとエンディアンを考慮する必要があります。

また、rawモードで構造体のデータにアクセスしたい場合は次のことができます。このよう

union message_with_raw 
{ 
    struct message msg; 
    uint8_t rawdata[sizeof(struct message)]; 
} 
+0

私は西で最速の銃です! (私たちはほぼ同じ答えを掲示しました:)) – Lundin

+0

@ Lundin。私は最初の部分、あなたの組合のために勝った+1 +1 – LPs

+0

DVので、私にヒットを与えることができますか????? – LPs

3

、それはあなたが16ビットの値として表現されるべきであるとエンディアンを決めるん強制以来:

// Little-endian. 
msg[1] = bytesToRead & 0xff; 
msg[2] = (bytesToRead >> 8) & 0xff; 

ビッグエンディアンの場合、右側の順序を逆にします。

3

あなたは、プロトコルのいくつかの並べ替えをデコードしているようですね、その一つの方法は、プロトコルデータに対応する構造体を宣言することです:

typedef struct 
{ 
    uint8_t something; 
    uint16_t bytes_to_read; 
} prot_data_t; 

次に便宜のために、とかわすのエイリアシングの問題には、あなたはこれを置くことができます

typedef union 
{ 
    prot_data_t named_data; 
    uint8_t  raw_data [sizeof(prot_data_t)]; 
} protocol_t; 

今、あなたはraw_dataを通じてデータを1バイトごとに送信/受信が、named_dataによって異なる値にアクセスすることができます:組合インチ


考慮すべきいくつかの点:

このコードだけでなく、すべてのソリューションは、ビットシフトを使用していないことに注意してくださいは、エンディアンに依存になります。

このようなコードは、整列と構造体/共用体パディングの問題を起こす可能性があります。移植性を最大限に高めるために、シリアライズ/デシリアライゼーションルーチンと組み合わせて使用​​しない限り、構造体/共用体は実際にはお勧めできません。

+0

...私もDVだった。笑...? – LPs

+0

'struct'パディングについて言及して本当にうれしいです。コンパイラ特有の構文を使ってGCCはそれを排除することができます(これはCPUがどのように整列したメモリ位置のみを扱うかは不明ですが、明らかにGCCと結びついています)。 – amn

2

そのような警告が理由であります。 msgが16ビット境界で開始する場合は、msg[1]はありません。したがって、そのフィールドのアドレスから始まる16ビットの値を書き込もうとすると、無効なメモリへの書き込みのトラップが発生し、クラッシュが発生する可能性があります。

代わりに、バイトを1つずつ書き込む必要があります。ビッグエンディアン形式(ネットワークバイトオーダーとも呼ばれます)でバイトを使用すると仮定すると、次のようになります。

msg[1] = (uint8_t)(bytesToRead >> 8); 
msg[2] = (uint8_t)(bytesToRead); 
+0

この「無効な書き込み」条件の性質について詳しく教えてください。 – amn

+0

@amn詳細については、http://stackoverflow.com/questions/19352232/unaligned-memory-accessを参照してください。 – dbush

関連する問題