想知道为什么指针算术不工作在asp.net
本文关键字:工作 asp net 为什么 指针 想知道 | 更新日期: 2023-09-27 18:01:34
我想尝试c#中的指针算术。我使用了一个asp.net web应用程序,期望它不会有问题,如果它是这个或控制台应用程序。
这是我尝试的:
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,0000000004 b5ca00,1,0000000004 b5c9fc,
我显然希望第二个是第一名。有人明白吗?
首先,如果您想了解堆栈是如何布局的,那么启动调试器并在调试器中查看堆栈似乎要容易得多。
假设出于某种原因你想继续编写程序来检查它们自己的堆栈状态:你过早地停止了实验。你应该写的程序是:
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"的地址会发生什么?它最后还会在堆栈上吗?也许不是!
这个问题与ASP.net无关。你对指针运算的使用是完全错误的。
对于几乎所有的编程语言来说,局部变量如何在堆栈上布局(或者它们是否在堆栈上)是未指定的。
逻辑局部变量存储的几个问题:
- 大多数编译器会把局部变量放到寄存器中,除非你得到它们的地址。
- 由lambda绑定的变量或
async
方法中的变量在堆对象上。 - 即使它们确实在堆栈上,顺序也是任意的。
- 逻辑变量和内存位置之间甚至没有1对1的对应关系。一旦变量超出作用域,内存位置可以被重用。
指针运算通常只能在单个分配的内存块中使用。
所以*(pB - 1)
对b
前面的内存解引用的结果为未指定行为。
在。net中,你通常可以在数组中使用指针算术或手动分配内存块。
您的第二个引用是对pB - 1的地址解引用,而不是对pB解引用并减去1。
对于返回值1的第二行,它需要读起来像这样:
Debug.WriteLine("{0:x16}",*(pB) - 1);
我不认为你可以或者应该对。net在内存中的位置做出任何假设。在您的情况下,*pB
正确地解析为2
,因为这是b
的值。我不认为你可以假设a
将被分配在b
之前,这样*(pB - 1)
就指向它了。你看到的是'堆栈上b
之前的int
'的整数值
当你写:
Debug.WriteLine("{0:x16}",*(pB - 1));
你正在取pB - 1
的内存位置的值。不是pB
- 1的值。
试着用这个:
Debug.WriteLine("{0:x16}",(*(pB) - 1));