C言語クイズ

http://twitter.com/nico_shindannin/status/33189937536827392

C言語クイズint a=1;func(a);printf("%d,a");void func(int x)内のコードを書いて、
このprintfで2を表示させるのじゃ。printfの書き換えは禁止で、各自の環境で動けば正解

どうという事もなく。

#include <stdio.h>

void func(int x) {
    *(&x + 8) = 2;
}
int main(void) {
    int a=1;
    func(a);
    printf("a=%d\n", a);
}

結果

awm.jp:~/prog/c% ./a.out
a=2

Intel 32bit Linux マシンで試しました。別の環境だと + 8 を変えないとダメかも。

+ 8 の調べ方

a は自動変数で x は引数なので、両方スタックにあるはず。
各々のポインタ値(アドレス)を調べる。

void func(int x) {
    printf("&x=%p\n", &x);
}
int main(void) {
    int a=1;
    func(a);
    printf("&a=%p\n", &a);
}
awm.jp:~/prog/c$ ./a.out
x=0xbf9e7350
a=0xbf9e7370

a の方が 0x20 大きい。32bit 機なら int は 4byte なので 0x20/4 = 8

*(&x + 8)

で、a 相当のアドレスの場所を書き換えられる。

それだけ。

引数がレジスタウィンドウに乗ったりして厄介な sparc でなくて良かったw
(-O0 でなんとかなるのかなぁ)