Can';在C#中是否可以使用t stackalloc来初始化先前声明的指针?

Can';在C#中是否可以使用t stackalloc来初始化先前声明的指针?,c#,stackalloc,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,如下所

我刚刚发现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上对它进行了测试,两者都不起作用。



您只能在声明和初始化局部变量时使用stackalloc。

可以理解,这是一种奇怪的行为……我不知道为什么,但它在MSDN上有记录

请看这里:


人们已经回答了这个问题,您只能在声明和初始化局部变量时使用它:

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

使用
stackalloc
时,编译器需要在堆栈上留出一些空间,减少堆栈指针,并在分配的变量超出范围时再次增加堆栈指针

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


因此,您必须明确地告诉编译器您希望将该变量分配到哪里,以及内存应该保留多长时间。

如果您解释了您期望发生的事情和实际发生的事情,这会有所帮助。以及为什么在C#中使用不安全代码。添加了错误消息。至于不安全代码,我肯定有我的用例,它与我的问题无关,我为什么要向你解释?我以为你在寻求帮助。当使用不规范的东西时,解释原因有助于找到合适的解决方案。随你的便。我编辑了标题以使其与问题更相关。感谢你的解释,似乎是合理的,但我们仍然可以在C
int*a=n>42中做同样的事情?(int*)malloc(sizeof(int)*n):(int*)alloca(sizeof(int)*n)和gcc没有抱怨。所以我认为,要让它工作,只需要一点任何编译器都能玩的小把戏。任何小把戏都不会对你有帮助,因为如果.NET CLR:可验证性的话,这会破坏一个基本的设计概念。在您的示例中,堆栈指针将在该指令之后具有不同的值。这是不允许的。堆栈指针在每个基本块的开头和结尾必须具有相同的值。@baulig,但我当然可以做到:
int*pOuter;{int*pInner=stackalloc int[1];*pInner=42;pOuter=pInner;}Console.WriteLine(*pOuter)
从程序员的角度来看,唯一重要的是地址,而不是变量。Martin,你混淆了IL操作数堆栈(这是一个用于验证目的的虚拟堆栈,它实际上与程序运行时的任何物理堆栈都对应)通过执行堆栈
stackalloc
从中分配。另外,应该注意的是,C++/CLI还允许在纯托管代码中使用
alloca()
(即使用/clr:pure编译时),这当然会编译为与C#
stackalloc
相同的IL,但没有任何限制。因此,这纯粹是一个C#限制,而不是CLR限制。