alloca(n) 和 char x[n] 有啥区别?
Posted
技术标签:
【中文标题】alloca(n) 和 char x[n] 有啥区别?【英文标题】:What's the difference between alloca(n) and char x[n]?alloca(n) 和 char x[n] 有什么区别? 【发布时间】:2011-02-06 13:24:29 【问题描述】:有什么区别
void *bytes = alloca(size);
和
char bytes[size]; //Or to be more precise, char x[size]; void *bytes = x;
...其中 size 是一个变量,其值在编译时未知。
【问题讨论】:
答案主要取决于size
是否是编译时常量。是吗?
不,对于所有意图和目的,size 是函数的参数
没关系。默认情况下,Apple 使用支持两者的--std=gnu99
。 alloca()
是 GNU 扩展,可变长度数组是符合标准的 C99 特性。
@Matt B.:Apple 与这些有什么关系?
@Billy:这个问题被标记为objective-c
。我知道 Mac 开发并不是 Obj-C 的唯一用途,但这是该语言最有可能的应用。我的观点是size
不必与 C99/gnu99 保持一致,并且它是 Xcode 中的默认模式。对我之前的评论的一个小的(稍微不相关的)更正是 s/Apple/Xcode/。
【参考方案1】:
alloca()
直到当前函数结束才回收内存,而变长数组在当前块结束时回收内存。
换一种说法:
void foo()
size_t size = 42;
if (size)
void *bytes1 = alloca(size);
char bytes2[size];
// bytes2 is deallocated here
; //bytes1 is deallocated here
alloca()
可以在任何 C89 编译器上(以某种方式)支持,而可变长度数组需要 C99 编译器。
【讨论】:
@Billy: char bytes[size] 分配的内存不保证在当前块结束时被物理回收;但是当前块之后的访问是不可能的了。 @Vlad:从技术上讲,C 标准很少提及实际需要物理存储的位置,以避免对特定架构的任何可能依赖。然而,即使标准中没有明确的内容,标准中的隐含含义也会导致 99.9% 的编译器以这种方式实现它。 好答案比利 :)。喜欢它。【参考方案2】:来自GNU documentation:
用 alloca 分配的空间一直存在,直到包含的 函数 返回。一旦数组名称的 范围 结束,可变长度数组的空间就会被释放。 (如果在同一个函数中同时使用可变长度数组和 alloca,释放可变长度数组也会释放最近分配的 alloca。)
此外,alloca
不是标准 C 函数,因此不能保证所有编译器都支持。可变长度数组是 C99 标准的一部分,因此任何支持 C99 的编译器都应该实现它。
【讨论】:
即使你的编译器不支持它,通常也有alloca
的公共域版本可用。
VLA 在 C11 中是可选的。【参考方案3】:
除了比利提到的一点,alloca
是非标准的(甚至在 C99 中也没有)。
【讨论】:
【参考方案4】:在第二种形式中,size
必须是编译时已知的常量。
【讨论】:
可能,但 OP 更可能指的是可变长度数组,它是 C99 标准的一部分。【参考方案5】:除了已经讨论过的关于何时释放空间以及是否完全支持该构造的要点之外,还有以下几点:
在alloca
的情况下,bytes
具有指针类型。
在[]
的情况下,bytes
具有数组类型。
最明显的区别在于sizeof(bytes)
是什么;对于指针,它是指针的大小(sizeof(void *)
),而对于数组,它是分配空间的大小(sizeof(char) * size
,对于这种情况,它 = size
,因为 sizeof(char)
= 1)。
(另外,在您的示例中,元素类型不同;要相同,应将第一个更改为char *bytes = alloca(size)
。)
【讨论】:
【参考方案6】:最大的不同是alloca在你使用内存作为类变量时不会调用构造函数或析构函数。
其他差异不太可能被注意到,但在某些情况下会在一些奇怪的运行时错误中变得明显。
【讨论】:
以上是关于alloca(n) 和 char x[n] 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
Java 中 给一个object 赋值属性, 既可以用构造函数的方式,也可以用setXXXX()的方式,而它们之间有啥区