以下は、32ビットの値の上位16ビット、下位16ビットを入れ替えるプログラムです。どうやら期待どおりに動作しているようなのですが、このままリリースしてしまうと問題が発生するかもしれません。

何が問題なのか分かりますか?
main.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
uint32_t ReversedHighLow32Helper(uint32_t n, uint32_t *pAs32, uint16_t *pAs16) {
*pAs32 = n;
uint16_t temp = pAs16[0];
pAs16[0] = pAs16[1];
pAs16[1] = temp;
return *pAs32;
}
uint32_t ReversedHighLow32(uint32_t n) {
uint32_t buffer;
return ReversedHighLow32Helper(n, &buffer, (uint16_t *)&buffer);
}
int main(void) {
uint32_t x = 0x11112222;
uint32_t y = ReversedHighLow32(x);
printf("x = 0x%08x\n", x);
printf("y = 0x%08x\n", y);
return EXIT_SUCCESS;
}
期待される実行結果
x = 0x11112222
y = 0x22221111

ちょっと複雑なプログラムだけど、解読できるかしら?

やってみます!

えっと、32ビットの値というのは、
main()
関数にあるx
のことかな。
uint32_t x = 0x11112222;
uint32_t y = ReversedHighLow32(x);

この
x
の値の上位16ビットと下位16ビットを入れ替えて、y
に代入してるんですね。

そうね。
x
の値は16進数で0x11112222
だから……

y
は0x22221111
になります!

正解!それじゃあ、実際の処理をしている部分はどうなってるかしら?

関数
ReversedHighLow32()
の中身ですね。

あれ?また別の関数を呼び出してる。この32ビットの変数
buffer
は……バッファ?
uint32_t ReversedHighLow32(uint32_t n) {
uint32_t buffer;
return ReversedHighLow32Helper(n, &buffer, (uint16_t *)&buffer);
}

で、この関数が呼ばれるのか。
uint32_t ReversedHighLow32Helper(uint32_t n, uint32_t *pAs32, uint16_t *pAs16) {
*pAs32 = n;
uint16_t temp = pAs16[0];
pAs16[0] = pAs16[1];
pAs16[1] = temp;
return *pAs32;
}

えっと、ここの引数は
n
が入れ替え前の値で、それにバッファへのポインタが2つありますね。

うんうん。
pAs32
とpAs16
の2つのポインタが、同じ32ビットのバッファを指しているわね。

あ、2つ目のポインタは
uint16_t *
ですね。え?これは16ビットでは……?

1つ目のポインタが指している32ビットの値を、2つ目のポインタでは16ビットの値が2つ格納された配列とみなしているわけ。

なるほど!配列だと思えば値を入れ替えられると。

そういうことよ。

そんなテクニックがあるんですねー!

そのテクニックがどうなの?っていうのが今回の問題よ。

えっと、いまいち問題の意味が理解できないんですけど……

そうね。まず今回のプログラムは、ひとまず期待どおりの動作をしているの。

あ、そうか。リリースすると問題が発生するっていう話でしたね。同じプログラムなのに?

そう。開発中とリリース時とでは、コンパイラの設定が違うでしょう?

そっか!ソースファイルが同じでも、コンパイル結果が変わるんですね。

そういうこと!

でも、だからって動作が変わったりします?

変わってしまうかもしれない、危険な書き方があるってことなのよ。

バッファへのアクセス方法に問題がないか考えてみましょう!