tags:

views:

228

answers:

4
main()
{
int i=256;
char buf[i];
}

perfectly compile on g++ but gives an error on visual studio 8.

anybody know why it is happening,

Thanks

+8  A: 

In C++, arrays have a constant size. In C99, however, there exist something called variable-length arrays, or VLA's. This is what you're making here.

g++ (the C++ compiler) is a sibling of gcc (the C compiler), and g++ is allowing you to use that C99 feature, while VS has no such thing. Essentially it's a non-standard C++ extension.

If you make i a compile-time constant, it would work (since that's standard C++):

const int i = 256; // obviously cannot change at runtime.

If you need a dynamic array in C++, use std::vector.


Note in C++ you need to specify a return type for main. This is and always shall be int.

GMan
I just checked and GCC goes beyond the C99 feature by supporting constructors in variable-sized stack arrays.
Potatoswatter
+1  A: 

Variable length arrays are allowed in C99, but not in Visual C++. VC++ is not based on C99.

Several additions of C99 are not supported in C++ or conflict with C++ features.

Source


With Visual C++ you can use a variable as the array size for the stack. But it must be a constant expression and determinable at compile time.

You can of course create a dynamically sized array at runtime by using the heap:

char *buf = new char[i];
//do something
delete[] buf;

But most of the time you would want to use an appropriate STL container such as std::vector.

Brian R. Bondy
Why would you suggest this over the much easier-to-use-correctly std::vector<char>?
Roger Pate
@Roger Pate: I think it is wrong to assume that std::vector<char> should be used in 100% of cases over a char buffer created on the heap. Of course both are useful and it depends on what your problem's context is. Thanks for the downvote though.
Brian R. Bondy
@Brian: I can't think of a single instance where a `vector` shouldn't be used and a raw allocation should. (Except while writing `vector` itself, etcetc.)
GMan
@GMan: How about for performance reasons?
Brian R. Bondy
@Brian: What performance difference is there? They do they same thing, one just cleans up after itself.
GMan
And in C++ we do that with `vector`. :) Only when someone has gone beyond what the standard library can do for them should they really be concerned with that stuff. Get them writing clean code first, understand how parts work together, then show them how the parts work. EDIT: I don't see how it could be different at all. All functions get inlined anyway. Maybe if you were using VS in Release without STL checks off, you may notice a slight difference, but that's just crappy implementation. :P Changed in VS2010, IIRC.
GMan
GMan: the most common problem with a std::vector is that it allocates space from the heap (usually by a call to `malloc` or equivalent). That can take a while compared to a stack allocation, which is usually a single add op. In my test environment, a small heap alloc costs about 200-1200 cycles, depending on cache state, whereas an `alloca` is 4.
Crashworks
@GMan: With a vector you have a constructor being called, and a destructor being called, and other overhead on top of your normal allocations. In most cases this won't matter, but wait until you need to call a function 10 million times in the course of a program executing, and this tiny performance gain adds up.
Brian R. Bondy
@Crashworks: Both Brian and I are talking about dynamic allocations here. @Brian: Constructor + `.reserve()` <-> `new[]`. Destructor <-> `delete[]`. Those are the equivalences, I can't see any time being lost from those. The compiler will literally convert a constructor call followed by a call to `new[]` to the same code. I just don't see any place the compiler can't inline everything to the same code we would have written by hand. And I don't understand your PHP comment, to be honest.
GMan
@GMan: I wouldn't say they are equivalences as I have profiled and found that to not be true on many occasions, and not all STL implementations are the same.
Brian R. Bondy
@GMan: Thank you for your input. You are right that what he is probably looking for is std::vector over an array on the heap. I updated my answer to still provide the same info as I was before, but to indicate that. I kept the information about the array on the heap because it is highly relevant to what the OP was asking, and in the past I have had situations where profiling code has shown me that an array on the heap gave me better performance than the associated vector code.
Brian R. Bondy
@Brian: I agree, it's a quality of implementation concern. That said, while you may be correct about some corner cases where a manually handled dynamic array is measurably better than a `vector`, those situations would be rare. Beginners, like the OP presumably is, should probably be taught the easiest and safest way to code.
GMan
@GMan: Agree, cheers. I do appreciate the critic on my answer focusing too much on corner cases and not aiming at what the OP was actually looking for. I'll keep this more in mind for future answers.
Brian R. Bondy
@Brian: No problem, glad we had a disagreement that stayed calm, that's not suppose to happen on the internet. :)
GMan
@Brian: The downvote is because "this answer is not useful" in showing new[]/delete[] to this OP. Even for performance reasons, if, for some reason, you can neither trust your stdlib implementations nor switch, it's trivial to use a thin limited-vector-like wrapper. The gains you get from RAII (and thus exception safety) and code clarity are huge and *very* significant---so much so that advice towards directly using new[] is slightly wrong.
Roger Pate
@Roger: I will respectfully disagree, the OP was asking about creating a dynamically sized array, and I showed him a way to accomplish that exactly. I think that is important to understand. And in my answer I modified it to suggest that "this is probably not what you want to do, you probably want to use `std::vector` instead".
Brian R. Bondy
A: 

In this case you can just use const:

int main()
{
    const int i=256;
    char buf[i];
}

Also note, that main without int as its return type is not valid C++.

Axel Gneiting
wouldn't you need the return 0; then? :)
Default
@Michael: `main` implicitly returns 0. :)
GMan
Actually, no, you wouldn't. `return 0;` is assumed if control leaves `main` without an actual return statement.
Dennis Zickefoose
well, I have learned something new today! Thanks GMan and Dennis :)
Default
+5  A: 

As said before, what you are doing isn't part of the C++ standard. However, you can create a variable-length array on the stack in C++ with:

{
  int length=256;
  char *buf = _alloca(length * sizeof(char)); // allocates space on the stack
      // that is freed when function returns
}

alloca() is not part of the standard either, but both gcc and Visual Studio support it. Be aware: the space it allocates is freed when you exit the function, not at the end of buf's scope! alloca() inside a loop will lead to suffering.

If you do not absolutely positively need your array to be on the stack instead of on the heap, then use a standard container like std::vector instead; it is on the heap, but knows how to clean up after itself.

Crashworks
`alloca` won't work with constructors or destructors. It's more portable not to use an underscore in the name. Get it from `stdlib.h` instead.
Potatoswatter
@Potato: *alloca* isn't portable to begin with---it's definitely not part of the standard C library
Roger Pate
@Roger: It's not standard, but it's implemented with identical semantics (assuming you only call it once per frame) on the vast majority of compilers.
Potatoswatter