依赖于函数参数的c++数组大小会导致编译错误

时间:2022-07-01 02:42:14

I have a simple function in which an array is declared with size depending on the parameter which is int.

我有一个简单的函数,在这个函数中,数组的大小取决于它的参数int。

    void f(int n){
        char a[n];
    };

    int main() {
        return 0;
    }

This piece of code compiles fine on GNU C++, but not on MSVC 2005.

这段代码在GNU c++上编译得很好,但是在MSVC 2005上却不行。

I get the following compilation errors:

我得到以下编译错误:

    .\main.cpp(4) : error C2057: expected constant expression
    .\main.cpp(4) : error C2466: cannot allocate an array of constant size 0
    .\main.cpp(4) : error C2133: 'a' : unknown size

What can I do to correct this?

我该怎么做才能改正呢?

(I'm interested in making this work with MSVC,without using new/delete)

(我对使用MSVC而不使用new/delete感兴趣)

7 个解决方案

#1


29  

What you have found it one of the Gnu compiler's extensions to the C++ language. In this case, Visual C++ is completely correct. Arrays in C++ must be defined with a size that is a compile-time constant expression.

您找到的是Gnu编译器对c++语言的扩展之一。在这种情况下,Visual c++完全正确。c++中的数组必须定义为一个编译时常量表达式的大小。

There was a feature added to C in the 1999 update to that language called variable length arrays, where this is legal. If you can find a C compiler that supports C99, which is not easy. But this feature is not part of standard C++, not is it going to be added in the next update to the C++ standard.

在1999年对该语言的更新中,有一个特性被添加到C中,称为可变长度数组,在这里这是合法的。如果你能找到一个支持C99的C编译器,这并不容易。但是这个特性不是标准c++的一部分,也不是在c++标准的下一个更新中添加的。

There are two solutions in C++. The first is to use a std::vector, the second is just to use operator new []:

c++有两个解。第一个是使用std::vector,第二个是使用算子new []:

char *a = new char [n];

While I was writing my answer, another one posted a suggestion to use _alloca. I would strongly recommend against that. You would just be exchanging one non-standard, non-portable method for another one just as compiler-specific.

当我在写我的答案时,另一个人发布了使用_alloca的建议。我强烈建议不要这么做。您只需将一个非标准的、不可移植的方法替换为另一个与编译器相关的方法。

#2


9  

Your method of allocating from the stack is a g++ extension. To do the equivalent under MSVC, you need to use _alloca:

您从堆栈分配的方法是一个g++扩展。要在MSVC下执行相同的操作,需要使用_alloca:

char *a = (char *)_alloca(n);

#3


5  

You are using something that is not a standard. Actually it is standard C but not C++. How peculiar is that!

你使用的不是标准的东西。实际上它是标准的C,而不是c++。这是多么奇特的!

Explaining a bit more, run time sized stack arrays are not part of C++, but are part of C99, the latest standard for C. That´s why some compilers will get it, while others will not. I would recommend refrain from using it, to avoid compiler compatibility issues.

解释多一点,运行时堆栈大小的数组并不是c++的一部分,但C99的一部分,最新的标准C´s为什么有些编译器会得到它,而另一些则不会。我建议不要使用它,以避免编译器兼容性问题。

The alternate implementation of the functionality would be using new and delete, as posted by strager.

该功能的替代实现将使用strager发布的新和删除操作。

#4


2  

You can use new/delete to allocate/free memory on the heap. This is slower and possibly more error prone than using char[n], but it's not part of the C++ standard yet, sadly.

您可以使用new/delete在堆上分配/释放内存。这比使用char[n]更慢,也可能更容易出错,但遗憾的是,它并不是c++标准的一部分。

You can used boost's scoped array class for an exception-safe method for using new[]. delete[] is automatically called on a when it goes out of scope.

您可以将boost的作用域数组类用于使用new[]的异常安全方法。当a超出范围时,delete[]将自动调用。

void f(int n) {
    boost::scoped_array<char> a(new char[n]);

    /* Code here. */
}

You can also use std::vector, and reserve() some bytes:

您还可以使用std::vector和reserve()一些字节:

void f(int n) {
    std::vector<char> a;
    a.resize(n);

    /* Code here. */
}

If you do want to use char[n], compile as C99 code instead of C++ code.

如果您确实想使用char[n],那么编译成C99代码而不是c++代码。

If you absolutely must allocate data on the stack for some reason, use _alloca or _malloca/_freea, which are extensions provided by MSVC libs and such.

如果由于某种原因必须在堆栈上分配数据,那么使用_alloca或_malloca/_freea,这是MSVC libs等提供的扩展。

#5


2  

variable length array was introduced in C99. It is supported in gcc but not msvc. According to a person in MSVC team, Microsoft has no plan to support this feature in their c/C++ compiler. He suggested to use std::vector in those cases.

在C99中引入了可变长度阵列。它在gcc中得到支持,但在msvc中没有。MSVC团队的一位人士表示,微软没有计划在其c/ c++编译器中支持这一功能。他建议在那些情况下使用std::vector。

Note that C99 does not require that the array allocated on the stack. The compiler can allocate it on the heap. However, gcc does allocate the array on the stack.

注意,C99不需要在堆栈上分配数组。编译器可以在堆上分配它。但是,gcc会在堆栈上分配数组。

#6


1  

Typically in C (excepting C99 compilers as others have pointed out) and C++, if you want to allocate memory on the stack, the size of what you want to allocate has to be known at compile time. Local variables are allocated on the stack, so an array whose length depends on a function parameter at run time violates this rule. Klein is correct to point out that using the 'new' operator is one way to solve this problem:

通常在C(除了其他人指出的C99编译器)和c++中,如果您想在堆栈上分配内存,那么必须在编译时知道要分配的内存大小。在堆栈上分配局部变量,因此运行时依赖函数参数的数组违反了这一规则。Klein指出,使用“新”运算符是解决这个问题的一种方法:


char *a = new char [n];

'a' is still a local variable allocated on the stack, but instead of being the whole array (which has variable length), it's just a pointer to an array (which is always the same size, and thus known at compile time). The array is allocated on the heap, which typically plays the stack's counterpart -- the stack is for things with a size known at compile time, and the heap is for things with a size not known at a compile time.

'a'仍然是在堆栈上分配的一个局部变量,但它不是整个数组(具有可变长度),而是指向数组的指针(总是相同的大小,因此在编译时是已知的)。数组被分配到堆上,堆通常扮演堆栈的对应角色——堆栈用于编译时已知的大小,堆用于编译时未知的大小。

#7


1  

Would it be reasonable to use a vector<> rather than an array? Or, since you're replacing a char *, a std::string? Those do work well with runtime sizing, although there may be other reasons not to use them.

使用向量<>而不是数组是否合理?或者,既然要替换char *, std::string?这些工具在运行时大小调整上运行得很好,尽管可能有其他原因不使用它们。

#1


29  

What you have found it one of the Gnu compiler's extensions to the C++ language. In this case, Visual C++ is completely correct. Arrays in C++ must be defined with a size that is a compile-time constant expression.

您找到的是Gnu编译器对c++语言的扩展之一。在这种情况下,Visual c++完全正确。c++中的数组必须定义为一个编译时常量表达式的大小。

There was a feature added to C in the 1999 update to that language called variable length arrays, where this is legal. If you can find a C compiler that supports C99, which is not easy. But this feature is not part of standard C++, not is it going to be added in the next update to the C++ standard.

在1999年对该语言的更新中,有一个特性被添加到C中,称为可变长度数组,在这里这是合法的。如果你能找到一个支持C99的C编译器,这并不容易。但是这个特性不是标准c++的一部分,也不是在c++标准的下一个更新中添加的。

There are two solutions in C++. The first is to use a std::vector, the second is just to use operator new []:

c++有两个解。第一个是使用std::vector,第二个是使用算子new []:

char *a = new char [n];

While I was writing my answer, another one posted a suggestion to use _alloca. I would strongly recommend against that. You would just be exchanging one non-standard, non-portable method for another one just as compiler-specific.

当我在写我的答案时,另一个人发布了使用_alloca的建议。我强烈建议不要这么做。您只需将一个非标准的、不可移植的方法替换为另一个与编译器相关的方法。

#2


9  

Your method of allocating from the stack is a g++ extension. To do the equivalent under MSVC, you need to use _alloca:

您从堆栈分配的方法是一个g++扩展。要在MSVC下执行相同的操作,需要使用_alloca:

char *a = (char *)_alloca(n);

#3


5  

You are using something that is not a standard. Actually it is standard C but not C++. How peculiar is that!

你使用的不是标准的东西。实际上它是标准的C,而不是c++。这是多么奇特的!

Explaining a bit more, run time sized stack arrays are not part of C++, but are part of C99, the latest standard for C. That´s why some compilers will get it, while others will not. I would recommend refrain from using it, to avoid compiler compatibility issues.

解释多一点,运行时堆栈大小的数组并不是c++的一部分,但C99的一部分,最新的标准C´s为什么有些编译器会得到它,而另一些则不会。我建议不要使用它,以避免编译器兼容性问题。

The alternate implementation of the functionality would be using new and delete, as posted by strager.

该功能的替代实现将使用strager发布的新和删除操作。

#4


2  

You can use new/delete to allocate/free memory on the heap. This is slower and possibly more error prone than using char[n], but it's not part of the C++ standard yet, sadly.

您可以使用new/delete在堆上分配/释放内存。这比使用char[n]更慢,也可能更容易出错,但遗憾的是,它并不是c++标准的一部分。

You can used boost's scoped array class for an exception-safe method for using new[]. delete[] is automatically called on a when it goes out of scope.

您可以将boost的作用域数组类用于使用new[]的异常安全方法。当a超出范围时,delete[]将自动调用。

void f(int n) {
    boost::scoped_array<char> a(new char[n]);

    /* Code here. */
}

You can also use std::vector, and reserve() some bytes:

您还可以使用std::vector和reserve()一些字节:

void f(int n) {
    std::vector<char> a;
    a.resize(n);

    /* Code here. */
}

If you do want to use char[n], compile as C99 code instead of C++ code.

如果您确实想使用char[n],那么编译成C99代码而不是c++代码。

If you absolutely must allocate data on the stack for some reason, use _alloca or _malloca/_freea, which are extensions provided by MSVC libs and such.

如果由于某种原因必须在堆栈上分配数据,那么使用_alloca或_malloca/_freea,这是MSVC libs等提供的扩展。

#5


2  

variable length array was introduced in C99. It is supported in gcc but not msvc. According to a person in MSVC team, Microsoft has no plan to support this feature in their c/C++ compiler. He suggested to use std::vector in those cases.

在C99中引入了可变长度阵列。它在gcc中得到支持,但在msvc中没有。MSVC团队的一位人士表示,微软没有计划在其c/ c++编译器中支持这一功能。他建议在那些情况下使用std::vector。

Note that C99 does not require that the array allocated on the stack. The compiler can allocate it on the heap. However, gcc does allocate the array on the stack.

注意,C99不需要在堆栈上分配数组。编译器可以在堆上分配它。但是,gcc会在堆栈上分配数组。

#6


1  

Typically in C (excepting C99 compilers as others have pointed out) and C++, if you want to allocate memory on the stack, the size of what you want to allocate has to be known at compile time. Local variables are allocated on the stack, so an array whose length depends on a function parameter at run time violates this rule. Klein is correct to point out that using the 'new' operator is one way to solve this problem:

通常在C(除了其他人指出的C99编译器)和c++中,如果您想在堆栈上分配内存,那么必须在编译时知道要分配的内存大小。在堆栈上分配局部变量,因此运行时依赖函数参数的数组违反了这一规则。Klein指出,使用“新”运算符是解决这个问题的一种方法:


char *a = new char [n];

'a' is still a local variable allocated on the stack, but instead of being the whole array (which has variable length), it's just a pointer to an array (which is always the same size, and thus known at compile time). The array is allocated on the heap, which typically plays the stack's counterpart -- the stack is for things with a size known at compile time, and the heap is for things with a size not known at a compile time.

'a'仍然是在堆栈上分配的一个局部变量,但它不是整个数组(具有可变长度),而是指向数组的指针(总是相同的大小,因此在编译时是已知的)。数组被分配到堆上,堆通常扮演堆栈的对应角色——堆栈用于编译时已知的大小,堆用于编译时未知的大小。

#7


1  

Would it be reasonable to use a vector<> rather than an array? Or, since you're replacing a char *, a std::string? Those do work well with runtime sizing, although there may be other reasons not to use them.

使用向量<>而不是数组是否合理?或者,既然要替换char *, std::string?这些工具在运行时大小调整上运行得很好,尽管可能有其他原因不使用它们。