我刚刚发现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上进行了测试,但都不起作用。
答案 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)