2

假设我有一个 C 函数:

void myFunction(..., int nObs){
    int myVec[nObs] ;
    ...
}

myVec 是动态分配的吗?每当调用 myFunction 时,nObs 都不是常量。我问是因为我目前正在使用这种习惯进行编程,而一个朋友的程序出现错误,罪魁祸首是他没有动态分配他的数组。我想知道我的编程习惯(如上例中的初始化)是否安全。

谢谢。

4

3 回答 3

3

要回答您的问题,它不被视为动态分配,因为它在堆栈中。在允许这样做之前,您可以在某些平台上使用 function 在堆栈上模拟相同的可变长度分配alloca,但这不是可移植的。这是(如果您为 C99 编程)。

于 2010-02-23T05:59:04.917 回答
1

它依赖于编译器。我知道 gcc 没问题,但我认为 C89 规范不允许这样做。我不确定更新的 C 规范,比如 C99。便携性的最佳选择是不要使用它。

于 2010-02-23T05:53:01.990 回答
1

它被称为“可变长度数组”。它是动态的,因为它的大小是在运行时确定的,并且可以随调用而改变,但它auto像任何其他局部变量一样具有存储类。我会避免为此使用“动态分配”一词,因为它只会让人感到困惑。

术语“动态分配”通常用于从堆分配的内存和对象,其生命周期由程序员确定(通过 new/delete、malloc/free),而不是对象的范围。可变长度数组在进入和离开范围时自动分配和销毁,就像任何其他具有auto存储类的局部变量一样。

编译器并不普遍支持可变长度数组;特别是 VC++ 不支持 C99(因此不支持可变长度数组),并且没有计划这样做。C++ 目前也不支持它们。

关于它是一种“安全习惯”,除了可移植性问题之外,显然存在溢出堆栈的可能性,应该nObs是一个足够大的值。nObs例如,您可以通过制作较小的整数类型uint8_t或例如在某种程度上防止这种情况发生uint16_t,但这不是一个非常灵活的解决方案,并且对堆栈的大小和正在分配的对象做出了大胆的假设。Anassert(nObs < MAX_OBS)可能是可取的,但此时堆栈可能已经溢出(这可能没问题,因为 assert() 在任何情况下都会导致终止)。

[编辑] 如果大小不是在您的示例中外部确定的,则使用可变长度数组可能没问题。[/编辑]

总的来说,可移植性和堆栈安全问题表明最好避免使用可变长度数组。

于 2010-02-23T15:21:36.310 回答