以下は、32ビットの値の上位16ビット、下位16ビットを入れ替えるプログラムです。どうやら期待どおりに動作しているようなのですが、このままリリースしてしまうと問題が発生するかもしれません。
![](/wp-content/include/images/avatar/teacher/5.png)
何が問題なのか分かりますか?
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
![](/wp-content/include/images/avatar/teacher/2.png)
ちょっと複雑なプログラムだけど、解読できるかしら?
![](/wp-content/include/images/avatar/student/5.png)
やってみます!
![](/wp-content/include/images/avatar/student/7.png)
えっと、32ビットの値というのは、
main()
関数にあるx
のことかな。
uint32_t x = 0x11112222;
uint32_t y = ReversedHighLow32(x);
![](/wp-content/include/images/avatar/student/3.png)
この
x
の値の上位16ビットと下位16ビットを入れ替えて、y
に代入してるんですね。
![](/wp-content/include/images/avatar/teacher/1.png)
そうね。
x
の値は16進数で0x11112222
だから……
![](/wp-content/include/images/avatar/student/8.png)
y
は0x22221111
になります!
![](/wp-content/include/images/avatar/teacher/4.png)
正解!それじゃあ、実際の処理をしている部分はどうなってるかしら?
![](/wp-content/include/images/avatar/student/4.png)
関数
ReversedHighLow32()
の中身ですね。
![](/wp-content/include/images/avatar/student/7.png)
あれ?また別の関数を呼び出してる。この32ビットの変数
buffer
は……バッファ?
uint32_t ReversedHighLow32(uint32_t n) {
uint32_t buffer;
return ReversedHighLow32Helper(n, &buffer, (uint16_t *)&buffer);
}
![](/wp-content/include/images/avatar/student/5.png)
で、この関数が呼ばれるのか。
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;
}
![](/wp-content/include/images/avatar/student/2.png)
えっと、ここの引数は
n
が入れ替え前の値で、それにバッファへのポインタが2つありますね。
![](/wp-content/include/images/avatar/teacher/1.png)
うんうん。
pAs32
とpAs16
の2つのポインタが、同じ32ビットのバッファを指しているわね。
![](/wp-content/include/images/avatar/student/11.png)
あ、2つ目のポインタは
uint16_t *
ですね。え?これは16ビットでは……?
![](/wp-content/include/images/avatar/teacher/6.png)
1つ目のポインタが指している32ビットの値を、2つ目のポインタでは16ビットの値が2つ格納された配列とみなしているわけ。
![](/wp-content/include/images/avatar/student/7.png)
なるほど!配列だと思えば値を入れ替えられると。
![](/wp-content/include/images/avatar/teacher/4.png)
そういうことよ。
![](/wp-content/include/images/avatar/student/3.png)
そんなテクニックがあるんですねー!
![](/wp-content/include/images/avatar/teacher/9.png)
そのテクニックがどうなの?っていうのが今回の問題よ。
![](/wp-content/include/images/avatar/student/2.png)
えっと、いまいち問題の意味が理解できないんですけど……
![](/wp-content/include/images/avatar/teacher/1.png)
そうね。まず今回のプログラムは、ひとまず期待どおりの動作をしているの。
![](/wp-content/include/images/avatar/student/10.png)
あ、そうか。リリースすると問題が発生するっていう話でしたね。同じプログラムなのに?
![](/wp-content/include/images/avatar/teacher/3.png)
そう。開発中とリリース時とでは、コンパイラの設定が違うでしょう?
![](/wp-content/include/images/avatar/student/8.png)
そっか!ソースファイルが同じでも、コンパイル結果が変わるんですね。
![](/wp-content/include/images/avatar/teacher/4.png)
そういうこと!
![](/wp-content/include/images/avatar/student/11.png)
でも、だからって動作が変わったりします?
![](/wp-content/include/images/avatar/teacher/10.png)
変わってしまうかもしれない、危険な書き方があるってことなのよ。
![](/wp-content/include/images/avatar/teacher/7.png)
バッファへのアクセス方法に問題がないか考えてみましょう!