2009年9月15日火曜日

ローカル変数のメモリ配置?


#include <stdio.h>
 
int main()
{
  int num = 0x00737569;
  int num2 = 0x61726144;
  printf("%s\n", (char*)&num2 );
  printf("%p, %p\n", (void*)&num, (void*)&num2 );
  return 0;
}

 というようなプログラムを実行したところgcc4.1.2では

Daraius
0xbfa284e8, 0xbfa284e4

 と、出力されたが、VisualC++2005EE(Debug)では

Daraフフフフフフフフius
0012FF4C, 0012FF40

 と表示された。Releaseだとgcc4.1.2と同じ結果になった。

 普通こんな使い方はしなけど面白半分にテストしてみたら自分の予想とは違った結果になった。
宣言した順番とは逆方向にメモリが確保されているのに「うん?」と思ったが、スタック構造なのを考えると納得はいく。構造体のイメージでいると「やっちゃったよ!」てな事態になるかもしれない。
 VC(debug)だと、intにもかかわらず12byteもの領域があるらしい。オプションの設定かなんかでそうなってるんだろうけど、Debugでは動くけどReleaseでは動かないなんて事態が容易に想像できるのが泣ける。


#include <stdio.h>
 
struct Block
{
  int num;
  int num2;
};
 
int main()
{
  struct Block b;
  b.num = 0x61726144;
  b.num2 = 0x00737569;
 
  printf("%s\n", (char*)&b.num );
  printf("%p, %p\n", (void*)&b.num, (void*)&b.num2 );
  return 0;
}

 を実行すると、gccでもVC(debug)でも同一の結果になった。「プログラミング言語C 第2版」の付録A8.3に構造体のメンバーは、宣言の順序に増えていくアドレスをもつ。とあるので、メモリ配置に関しては信用できる。intが4byteとは限らないし、char*に変換したときに[0]44,[1]61,[2]72,[3]61となるとも(おそらく)限らないので、結局環境依存だけど。

 いままで、ノリと勘だけでやってたから、知らんことばっかりじゃ。

0 件のコメント: