日期:2014-05-18  浏览次数:21007 次

C#指针的问题
考虑以下代码:
C# code

unsafe
            {
                byte b = 3;
                double d = 10.0;
                int i = 5;

                byte* pb = &b;
                double* pd = &d;
                int* pi = &i;

                Console.WriteLine("Address of b is 0x{0:X},size is {1},value is {2}", (uint)pb, sizeof(byte), b);
                Console.WriteLine("Address of d is 0x{0:X},size is {1},value is {2}", (uint)pd, sizeof(double), d);
                Console.WriteLine("Address of i is 0x{0:X},size is {1},value is {2}", (uint)pi, sizeof(int), i);

                Console.WriteLine("Address of pb is 0x{0:X},size is {1},value is 0x{2:X}", (uint)&pb, sizeof(byte*), (uint)pb);
                Console.WriteLine("Address of pd is 0x{0:X},size is {1},value is 0x{2:X}", (uint)&pd, sizeof(double*), (uint)pd);
                Console.WriteLine("Address of pi is 0x{0:X},size is {1},value is 0x{2:X}", (uint)&pi, sizeof(int*), (uint)pi);
            }


在我机子上显示的输出结果是
Address of b is 0x12F46C,size is 1,value is 3
Address of d is 0x12F464,size is 8,value is 10
Address of i is 0x12F460,size is 4,value is 5
Address of pb is 0x12F45C,size is 4,value is 0x12F46C
Address of pd is 0x12F458,size is 4,value is 0x12F464
Address of pi is 0x12F454,size is 4,value is 0x12F460

现在我的问题是:看代码,堆栈应该是从高地址向低地址向下填充,byte只占1个字节,而32位处理器系统堆栈的内存块总是按照4字节的倍数进行分配的。b的地址是0x12F46C,那么b这个值应该存储在0x12F468~0x12F46B中,占4个字节,然后为d分配内存,double类型占8个个字节,其地址应该是0x12F468,d应该存储在0x12F460~0x12F467中,但为什么输出结果b占了8个字节的内存而d却只占了4个字节的内存呢。
另外如果把代码的最后三行去掉,即变成
C# code

unsafe
            {
                byte b = 3;
                double d = 10.0;
                int i = 5;

                byte* pb = &b;
                double* pd = &d;
                int* pi = &i;

                Console.WriteLine("Address of b is 0x{0:X},size is {1},value is {2}", (uint)pb, sizeof(byte), b);
                Console.WriteLine("Address of d is 0x{0:X},size is {1},value is {2}", (uint)pd, sizeof(double), d);
                Console.WriteLine("Address of i is 0x{0:X},size is {1},value is {2}", (uint)pi, sizeof(int), i);
}


输出结果为
Address of b is 0x12F45C,size is 1,value is 3
Address of d is 0x12F460,size is 8,value is 10
Address of i is 0x12F468,size is 4,value is 5
内存分配变成了从低地址到高地址向上填充,但此时b占了4个字节,d占了8个字节,何解?

------解决方案--------------------
我觉得吧,那个Address of b is 0x12F45C的0x12F45C是起始地址
比如:
Address of b is 0x12F46C,size is 1,value is 3 b在0x12F46C-0x12F46F 4字节
Address of d is 0x12F464,size is 8,value is 10 d在0x12F464-0x12F46B 8字节
Address of i is 0x12F460,size is 4,value is 5 i在0x12F460-0x12F463 4字节
Address of pb is 0x12F45C,size is 4,value is 0x12F46C 同上
Address of pd is 0x12F458,size is 4,value is 0x12F464 ……
Address of pi is 0x12F454,size is 4,value is 0x12F460 ……

而下面的也一样
Address of b is 0x12F45C,size is 1,value is 3 b在0x12F45C-0x12F45F 4字节
Address of d is 0x12F460,size is 8,value is 10 d在0x12F460-0x12F467 8字节
Address of i is 0x12F468,size is 4,value is 5

至于为什么前面的例子是从高向低分配,后面的例子反过来,就不得而知了……
佩服楼主钻研的精神,不过好像不是很有这个必要……
------解决方案--------------------
you cannot use sizeof to get the size of 'native storage'. You might use Marshal.Sizeof instead:
C# code

   int i = Marshal.SizeOf( typeof(bool) );  // i = 4
   int j = siz