不能在C#中使用stackalloc来初始化先前声明的指针吗?

时间:2012-11-09 12:38:23

标签: c# stackalloc

我刚刚发现C#的stackalloc符号有一个令人难以置信的怪癖,请参阅以下代码:

//          int *p;
//          p = stackalloc int[42];  // won't work! 
//  Error CS1525: Unexpected symbol `stackalloc' (CS1525) 

            int *p = stackalloc int[42]; //works

我的意图是在这样的三元表达式中使用stackalloc:

int *p = size > 0xFFFFF ? (int*)Marshal.AllocHGlobal(size).ToPointer() : stackalloc int[size];

编译器完全意想不到的罢工让我感到震惊。如果有人能对这种奇怪的行为有所了解,我真的很感激。我已经在mono和.net上进行了测试,但都不起作用。

3 个答案:

答案 0 :(得分:9)

http://msdn.microsoft.com/en-us/library/cx9s2sy4(v=vs.100).aspx
只有在声明和初始化局部变量时才能使用stackalloc。

答案 1 :(得分:5)

人们已经回答过这个问题,你只能在声明和初始化局部变量时使用它:http://msdn.microsoft.com/en-us/library/cx9s2sy4(v=vs.110).aspx

然而,如果你想知道这是什么原因,那就是词汇范围。局部变量声明创建包含一个或多个基本块的词法范围。 CLR要求堆栈指针位于每个这样的基本块的开头和结尾处的相同位置。控制传输语句只能跳转到基本块的第一条指令。

当你使用stackalloc时,编译器需要通过递减堆栈指针并在分配的变量超出范围时再次递增它来在堆栈上留出一些空间。

如果你在表达式评估中,堆栈上会有临时值,那么编译器应该在哪里放置该变量?在方法开头分配它不是一个选项,因为您可以使用表达式来指定大小。

因此,您必须明确告诉编译器您希望分配变量的位置以及应保留内存的时间。

答案 2 :(得分:0)

可以理解这是一种古怪的行为......我没有答案为什么,但它在MSDN上有记录

见这里:

http://msdn.microsoft.com/en-us/library/cx9s2sy4.aspx