想知道为什么指针算法在asp.net中不起作用

时间:2011-07-07 18:41:04

标签: c# math pointers

我想在c#中尝试指针运算。我使用了一个asp.net网络应用程序,期望无论是这个还是控制台应用都没关系。

这是我试过的:

public class memorytest
{
    public class Sample
    {
        public int A;
        public int B;
        public int C;
        public int D;
    }

   public static unsafe void Main()
   {
    Sample s = new Sample {A = 1, B = 2, C = 3, D = 4};
    int a = 1;
    int b = 2;
    int* pA = &a;
    int* pB = &b;
    Debug.WriteLine("{0:x16}",* pB);
    Debug.WriteLine("{0:x16}",*(pB - 1));
    Debug.WriteLine(*pA);
    Debug.WriteLine("{0:x16}",*(pB - 2));
    }

}

结果是这样的:

0000000000000002, 0000000004b5ca00, 1, 0000000004b5c9fc,

我显然希望第二个是数字1.有人理解这个吗?

5 个答案:

答案 0 :(得分:10)

首先,如果你想了解堆栈是如何布局的,那么启动调试器并查看调试器中的堆栈似乎要容易得多。

假设由于某种原因你想继续编写程序来检查自己的堆栈状态:你过早地停止了试验。你应该写的程序是:

Debug.WriteLine("{0:x16}",*(pB - 1));
Debug.WriteLine("{0:x16}",*(pB + 0));    
Debug.WriteLine("{0:x16}",*(pB + 1));

然后你就得到了输出

00000badf00dd00d  <-- some pointer value
0000000000000002  <-- contents of b
0000000000000001  <-- contents of a

你会得知堆栈的增长方向与你认为的相反。在许多架构中,将某些东西推入堆栈减少了堆栈指针。

当然,正如其他人所指出的那样,我们不保证堆栈上的东西是如何布置的,或者即使东西首先进入堆栈也是如此;在某些情况下,局部变量可以放在堆上,并且可以注册其地址永远不会被占用的局部变量。例如,如果你不采用“a”的地址会发生什么?它是否仍然在堆栈中?也许不吧!

答案 1 :(得分:6)

此问题与ASP.net无关。你对指针算法的使用是完全错误的。

局部变量如何在堆栈上布局(或者如果它们甚至在堆栈上)几乎没有任何编程语言。

存储逻辑局部变量的一些复杂情况:

  • 大多数编译器会将局部变量放在寄存器中,除非你得到他们的地址。
  • 由lambda绑定的变量,或async方法中的变量都在堆对象上。
  • 即使他们确实在堆叠上,订单也是任意的。
  • 逻辑变量和内存位置之间甚至没有1对1的对应关系。一旦变量超出范围,就可以重用内存位置。

指针运算通常只能在一个分配的内存块中使用。

因此*(pB - 1)取消引用b前面的内存的结果是未指定的行为。

在.net中,您通常可以在数组内部使用指针算法或手动分配内存块。

答案 2 :(得分:4)

您的第二个引用是取消引用pB - 1的地址,而不是取消引用pB并减去1。

对于第二行返回值为1,需要读取如下:

Debug.WriteLine("{0:x16}",*(pB) - 1);

答案 3 :(得分:1)

我认为你不能或不应该对内存中的WHERE进行任何假设.NET会放置你的变量。在您的情况下,*pB会正确解析为2,因为这是b的值。我认为您不能认为a将在b之前分配,*(pB - 1)指向int。您在堆栈上看到b之前的任何一个{{1}}的整数值。

答案 4 :(得分:0)

当你写:

Debug.WriteLine("{0:x16}",*(pB - 1)); 

您正在获取pB - 1的内存位置值。不是pB减去1的值。

尝试使用:

Debug.WriteLine("{0:x16}",(*(pB) - 1));