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
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.
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.
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.
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++.
Related
double rainPerMonth(const int YEARS)
{
int monthYear[MONTHS][YEARS];
// ...
}
Visual Studio shows a squiggly line underneath the array declaration, saying that YEARS must be a constant when I'm creating the array. Is this an IDE issue because the variable has yet to be initialized, or am I writing this incorrectly?
MONTHS is already declared globally.
An array size must be a constant expression - that is, a value known at compile time. (Some compilers offer C-style variable-length arrays as a non-standard extension, but I don't think Visual C++ does. Even if it does, it's better not to rely on such extensions.)
A function argument isn't known at compile time, so can't be used as an array size. Your best option is here is probably
std::vector<std::array<int, MONTHS>> monthYear(YEARS);
In C++, an array must be sized at compile time. What you are attempting to do is declare one that is sized at runtime. In the function you've declared, YEARS is only constant within the scope of the function. You could call it rainPerMonth(someInt); where someInt is the result of some user input (which shows you that the result is not a compile-time constant).
Variable Length Arrays are an extension to C, but not C++. To do what you want, you can use dynamic memory, or a std::vector.
I think your problem lies in the fact that C++ wants a constant in the sense of compile-time constant to create your variable monthYear. If you pass it as a function, it need not be known at compile time? For example:
const int x=2;
const int y=3;
char xyChoice;
std::cin >> xyChoice;
if (xyChoice == 'x')
rainPerMonth(x);
else
rainPerMonth(y);
I'm unsure, but it seems to me like this would give you a constant int being passed to your function, but the compiler wouldn't know what size to create an array for before runtime?
I know that int* array = new int [n]; allocates memory space in heap.
But if I declare something like that: int array[n]; in codeblocks it compile successfully, but if I move it to visual studio, it comes out of error.
What I want to ask is:
What does int[n] really do and how does it compare to heap allocation? What is the difference between them?
What the error may come out if I use int array[n] instead of int* array = new int [n];?
int array[n] declares an array on the stack, not the heap. In standard C++ n must be a compile time constant, however some compilers have an extension that allows for variable length arrays declared in this form without a compile time constant n. It's not standard and probably shouldn't be used.
int array[n] can cause a couple problems over int* array = new int [n];:
If n is big enough you can cause a stack overflow. Or if the array is a class member and you create a large array of the class.
If array is a class member moving could be as expensive as copying
If array is a class member and you have given out pointers to the array and move the class, the pointers now refer to a post-moved object, or if random memory if the object was also destroyed. Either way, bad.
GCC has an extension in C++ that allows int array[n] where n is not a compile time constant value. The standard language doesn't allow you to use non-constant value for n in such a case (it is allowed in C99).
If I understand your questions correctly, then I can answer both.
int array[10] is allocated on the stack, whereas int *array = new int[10] is allocated on the heap. Usually, stack arrays only work with a constant number of elements, so int array[n] is not allowed in C90 (as long as n is not constant).
MinGW (which is the version of the GCC compiler that codeblocks uses on windows) has an extension which does allow you to write int array[n] in C90 mode, where n is not constant. Visual C++ does not allow this.
when you write int array[n], that means you are performing a static allocation. i.e. memory will be allocated at the compile time. So using a variable length here will result in a compile time error.
I have some concepts about the VLA and its behavior that I need to clarify.
AFIK since C99 it's possible to declare VLA into local scopes:
int main(int argc, char **argv)
{
// function 'main' scope
int size = 100;
int array[size];
return 0;
}
But it is forbidden in global scopes:
const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++
int main(int argc, char **argv)
{
int local_size = 100;
int local_array[local_size];
return 0;
}
The code above declares a VLA in C99 because the const modifier doesn't create a compile-time value. In C++ global_size is a compile-time value so, global_array doesn't become a VLA.
What I need to know is: Is my reasoning correct? Is the behaviour that I've described correct?
I also want to know: Why are the VLA not allowed in global scope? are they forbidden both in C and C++? Why is the behavior of arrays into global and local scope different?
Yes your reasoning is correct, that is how these different forms of array declarations and definitions are viewed by C and C++.
As others already stated, VLA with a veritable variable length (non-const) in global scope is difficult to make sense. What would the evaluation order be, e.g if the the length expression would refer to an object of a different compilation unit? C++ doesn't have VLA, but it has dynamic initialization of objects at file scope. And already this gives you quite a head ache, if you have to rely on evaluation order.
This leaves the small gap for C concerning length expressions that contain a const qualified object, which isn't allowed. This comes from the fact that such objects are not considered "integer constant expressions" by the C standard. This could perhaps change in future versions, but up to now the C committee didn't find it necessary to allow for such a thing: there are enum constants that play that role in C. Their only limitation is that they are limited to int in C, it would be nice to also have them size_t.
C++ doesn't support VLAs, period. The reason the second code snippet works in C++ is that the const keyword creates a compile-time constant in C++; in C, it doesn't.
C99 doesn't support VLAs outside of block scope, period, regardless of how you declare the size variable. Note that C2011 makes VLA support optional.
There is a difference between being forbidden and not being allowed. ;-)
The VLA feature is designed to allow the use of stack space for a local array, to avoid the use of malloc for heap allocation. It is mostly a speed optimization.
Now you want to use VLAs outside of functions. Why? There is not much to win speedwise in avoiding a single malloc call during program start. And what stack space are we supposed to use for variables with a static life time?
I think the fundamental reason is a global variable has linkage, its size has to be known at compile time. If not, how could one link the program?
local variables have no linkage and the VLAs are allocated on the stack, which grows dynamically as the program runs.
So, for global VLA's, one of the issues (there are many variants on the theme) can be shown here:
int size;
int a;
int v[size];
int b;
....
in another file:
extern int a;
extern int b;
The linker will have to know where a and be are in relation to each other at link time, or it won't be able to fix them up correctly at load-time.
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
int size;
cin >> size;
int myArray[size]; //this shouldn't compile , right ?
return 0;
}
I thought this wouldn't compile, but it does actually (using the g++ command).
What I found out later is that GCC actually allows variable-size arrays even if by standard C++ doesn't support variable-size arrays, Which is weird ! Because I hear everyone saying that the only way to create a variable-size array is to use dynamic allocation like int* array = new int[size]; or better std::vector. I thought GCC wouldn't allow that piece of code !
Anyway, My theoretical question is, the myArray array is allocated in the heap or stack area ?
That is an extension on the compiler side. How does it work? Well, it works only to some extent.
The implementation basically moves the stack pointer a quantity that is dependent on the size of the array, and calls the memory in the middle by the name of the array. It only works to some extent because in VLAs the size is not an integral part of the type, which means that many constructs that can be used on regular arrays cannot be done with this type, like for example passing the array to a template by reference... sizeof is usually supplied but implemented as a runtime construct.
myArray in your example is allocated on the stack. g++ has an extension that allows this trick. The heap isn't necessary to do this, the compiler just generates code to increase the stack pointer by an amount that is computed at run time.
VLAs are an extension, many implementations have there own extensions to the C++ language. If you want g++ to complain that you are not adhering to the standard, pass -pedantic flag. VLAs are on the stack which is really fast, however, this is also the cause of problems since you have limited stack space. In C++ however, we have constructs like std::vector, etc., so there is really no need for there use.
Just curious, what actually happens if I define a zero-length array int array[0]; in code? GCC doesn't complain at all.
Sample Program
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Clarification
I'm actually trying to figure out if zero-length arrays initialised this way, instead of being pointed at like the variable length in Darhazer's comments, are optimised out or not.
This is because I have to release some code out into the wild, so I'm trying to figure out if I have to handle cases where the SIZE is defined as 0, which happens in some code with a statically defined int array[SIZE];
I was actually surprised that GCC does not complain, which led to my question. From the answers I've received, I believe the lack of a warning is largely due to supporting old code which has not been updated with the new [] syntax.
Because I was mainly wondering about the error, I am tagging Lundin's answer as correct (Nawaz's was first, but it wasn't as complete) -- the others were pointing out its actual use for tail-padded structures, while relevant, isn't exactly what I was looking for.
An array cannot have zero size.
ISO 9899:2011 6.7.6.2:
If the expression is a constant expression, it shall have a value greater than zero.
The above text is true both for a plain array (paragraph 1). For a VLA (variable length array), the behavior is undefined if the expression's value is less than or equal to zero (paragraph 5). This is normative text in the C standard. A compiler is not allowed to implement it differently.
gcc -std=c99 -pedantic gives a warning for the non-VLA case.
As per the standard, it is not allowed.
However it's been current practice in C compilers to treat those declarations as a flexible array member (FAM) declaration:
C99 6.7.2.1, ยง16: As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
The standard syntax of a FAM is:
struct Array {
size_t size;
int content[];
};
The idea is that you would then allocate it so:
void foo(size_t x) {
Array* array = malloc(sizeof(size_t) + x * sizeof(int));
array->size = x;
for (size_t i = 0; i != x; ++i) {
array->content[i] = 0;
}
}
You might also use it statically (gcc extension):
Array a = { 3, { 1, 2, 3 } };
This is also known as tail-padded structures (this term predates the publication of the C99 Standard) or struct hack (thanks to Joe Wreschnig for pointing it out).
However this syntax was standardized (and the effects guaranteed) only lately in C99. Before a constant size was necessary.
1 was the portable way to go, though it was rather strange.
0 was better at indicating intent, but not legal as far as the Standard was concerned and supported as an extension by some compilers (including gcc).
The tail padding practice, however, relies on the fact that storage is available (careful malloc) so is not suited to stack usage in general.
In Standard C and C++, zero-size array is not allowed..
If you're using GCC, compile it with -pedantic option. It will give warning, saying:
zero.c:3:6: warning: ISO C forbids zero-size array 'a' [-pedantic]
In case of C++, it gives similar warning.
It's totally illegal, and always has been, but a lot of compilers
neglect to signal the error. I'm not sure why you want to do this.
The one use I know of is to trigger a compile time error from a boolean:
char someCondition[ condition ];
If condition is a false, then I get a compile time error. Because
compilers do allow this, however, I've taken to using:
char someCondition[ 2 * condition - 1 ];
This gives a size of either 1 or -1, and I've never found a compiler
which would accept a size of -1.
Another use of zero-length arrays is for making variable-length object (pre-C99). Zero-length arrays are different from flexible arrays which have [] without 0.
Quoted from gcc doc:
Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure that is really a header for a variable-length object:
struct line {
int length;
char contents[0];
};
struct line *thisline = (struct line *)
malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
In ISO C99, you would use a flexible array member, which is slightly different in syntax and semantics:
Flexible array members are written as contents[] without the 0.
Flexible array members have incomplete type, and so the sizeof operator may not be applied.
A real-world example is zero-length arrays of struct kdbus_item in kdbus.h (a Linux kernel module).
I'll add that there is a whole page of the online documentation of gcc on this argument.
Some quotes:
Zero-length arrays are allowed in GNU C.
In ISO C90, you would have to give contents a length of 1
and
GCC versions before 3.0 allowed zero-length arrays to be statically initialized, as if they were flexible arrays. In addition to those cases that were useful, it also allowed initializations in situations that would corrupt later data
so you could
int arr[0] = { 1 };
and boom :-)
Zero-size array declarations within structs would be useful if they were allowed, and if the semantics were such that (1) they would force alignment but otherwise not allocate any space, and (2) indexing the array would be considered defined behavior in the case where the resulting pointer would be within the same block of memory as the struct. Such behavior was never permitted by any C standard, but some older compilers allowed it before it became standard for compilers to allow incomplete array declarations with empty brackets.
The struct hack, as commonly implemented using an array of size 1, is dodgy and I don't think there's any requirement that compilers refrain from breaking it. For example, I would expect that if a compiler sees int a[1], it would be within its rights to regard a[i] as a[0]. If someone tries to work around the alignment issues of the struct hack via something like
typedef struct {
uint32_t size;
uint8_t data[4]; // Use four, to avoid having padding throw off the size of the struct
}
a compiler might get clever and assume the array size really is four:
; As written
foo = myStruct->data[i];
; As interpreted (assuming little-endian hardware)
foo = ((*(uint32_t*)myStruct->data) >> (i << 3)) & 0xFF;
Such an optimization might be reasonable, especially if myStruct->data could be loaded into a register in the same operation as myStruct->size. I know nothing in the standard that would forbid such optimization, though of course it would break any code which might expect to access stuff beyond the fourth element.
Definitely you can't have zero sized arrays by standard, but actually every most popular compiler gives you to do that. So I will try to explain why it can be bad
#include <cstdio>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
int empty[0];
};
A vals[3];
}
I am like a human would expect such output:
A()
A()
A()
~A()
~A()
~A()
Clang prints this:
A()
~A()
GCC prints this:
A()
A()
A()
It is totally strange, so it is a good reason not to use empty arrays in C++ if you can.
Also there is extension in GNU C, which gives you to create zero length array in C, but as I understand it right, there should be at least one member in structure prior, or you will get very strange examples as above if you use C++.