我想在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));
}
}
Run Code Online (Sandbox Code Playgroud)
结果是这样的:
0000000000000002,0000000004b5ca00,10000004b5c9fc,
我显然希望第二个是数字1.有人理解这一点吗?
Eri*_*ert 10
首先,如果你想了解堆栈是如何布局的,那么启动调试器并查看调试器中的堆栈似乎要容易得多.
假设由于某种原因你想继续编写程序来检查自己的堆栈状态:你过早地停止了试验.你应该写的程序是:
Debug.WriteLine("{0:x16}",*(pB - 1));
Debug.WriteLine("{0:x16}",*(pB + 0));
Debug.WriteLine("{0:x16}",*(pB + 1));
Run Code Online (Sandbox Code Playgroud)
然后你会得到输出
00000badf00dd00d <-- some pointer value
0000000000000002 <-- contents of b
0000000000000001 <-- contents of a
Run Code Online (Sandbox Code Playgroud)
而你会发现堆栈的生长方向与你认为的相反.在许多架构中,将某些东西推入堆栈会减少堆栈指针.
当然,正如其他人所指出的那样,我们不保证堆栈上的东西是如何布置的,或者即使东西首先进入堆栈也是如此; 在某些情况下,局部变量可以放在堆上,并且可以注册其地址永远不会被占用的局部变量.例如,如果你不采用"a"的地址会发生什么?它是否仍然在堆栈中?也许不吧!
这个问题与ASP.net无关.你使用指针算术是完全错误的.
局部变量如何在堆栈上布局(或者如果它们甚至在堆栈上)几乎都没有指定任何编程语言.
存储逻辑局部变量的一些复杂情况:
async方法中的变量都在堆对象上.指针运算通常只能在单个分配的内存块中使用.
因此*(pB - 1),取消引用前面的内存的结果b是未指定的行为.
在.net中,您通常可以在数组内部使用指针算法或手动分配内存块.