views:

3124

answers:

7

I have a simple function in which an array is declared with size depending on the parameter which is 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.

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)

+7  A: 

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

char *a = (char *)_alloca(n);
Jim Buck
Oh so it allocates on stack ! that's marvelous :) Thanks !
xxxxxxx
Note this comment from the alloca manpage:BUGS The alloca function is machine and compiler dependent. On many systems its implementation is buggy. Its use is discouraged.
Nathan Fellman
Yeah, but it works for sure under MSVC, which is what the OP was trying to get his code working under. I've been using it myself for years.
Jim Buck
+1  A: 

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.

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.

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

    /* Code here. */
}

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

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.

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.

strager
yes but I don't understand why g++ has no problem with this while MSVC fails
xxxxxxx
This is wrong since it allocates from the heap. He wants to allocate on the stack which is what the g++ version does. The reason that MSVC doesn't compile the original version is that it is a g++ extension.
Jim Buck
He can't have it on the stack with MSVC. He can have it on the heap, or have it be constant sized, there is no way to allocate a variably sized array on the stack with MSVC.
Michael Kohne
Yes you can. See my answer. (Hint: _alloca :) )
Jim Buck
@Jim Buck _alloca is the same as using new/delete and this was known to me before I have posted. @strager I have specified that I am sure I am compiling C++ code right from the very beggining(see title of this post).
xxxxxxx
No, _alloca allocates from the stack (compiles to a single instruction), and new/delete allocates from the heap (expensive operation). If performance doesn't matter, totally go for the cleanest and most portable code, though.
Jim Buck
@strager yes those functions you mentioned seem to be ok as they are also [mentioned here](http://msdn.microsoft.com/en-us/library/5471dc8s(VS.80).aspx)
xxxxxxx
i think you have a typo. Didn't you want to use .resize(n) instead of reserve(n) ?
Johannes Schaub - litb
@litb, I think it could go either way. But you're right -- resize is probably better than reserve.
strager
To make it as compatible as possible, use .resize(). That means there is an array there, and something like a[2] (assuming n >= 3) is fully meaningful. .reserve() means to allow for a future array of size n.
David Thornley
+16  A: 

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.

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.

There are two solutions in C++. The first is to use a std::vector, the second is just to use operator 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.

Jack Klein
Yeah, but allocating from the heap, which "new" does, is much different from allocating from the stack which is what the OP is trying to do. (It could be performance-sensitive code he's trying to compile.)
Jim Buck
Not so much worries about performance for the moment,I thought it was natural to work...but if it's not part of the C++ standard then I understand
xxxxxxx
Re: _alloca: OP only asked about getting equivalent code working on MSVC and without using new/delete.
Jim Buck
+2  A: 

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

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.

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

David Reis
A: 
Joseph Garvin
A: 

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.

David Thornley
A: 

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.

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.

Sherwood Hu