This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 8 years ago.
The code compiles and runs, but is it legal? AFAIK, size of static array must be known at compile time.
#include <iostream>
void foo(const unsigned size){
double arr[size];
for(auto& i:arr){
i=2;
std::cout << i;
}
}
int main(){
unsigned size;
std::cin >> size;
foo(size);
}
Strictly speaking, this is not legal. Variable length arrays (VLA) are not supported by standard C++. VLA are supported by most compilers an an extension but using those may give you non portable behavior.
Also, there is no static array in your source code. To do so you would need to use the static keyword on the declaration.
As user657267 mentioned, Runtime-size arrays have been discussed for C++14 in N3639 and another similar feature, std::dynarray has been discussed, however they have been rejected for C++14.
Currently, this is not considered as part of the standard although some compilers implemented this as non-portable extensions, gcc for example is one of these compilers (possibly because this is legal in C99).
Most of the time, you can just use a vector to the same effect.
In your example there is no array with the static storage duration. There is a local array within a function with automatic storage duration.
The size of the array shall be a constant expression.
If the code you showed is compiled then it means it is a feature of the compiler that supports Variable Length Arrays in C++ the same way as in C.
Related
This question already has an answer here:
VLAs when compiling a C++ source with g++
(1 answer)
Closed 7 years ago.
I just read a tutorial about dynamic memory in C++ and it states as follows:
...the size of a regular array needs to be a constant expression, and thus its size has to be determined at the moment of designing the program, before it is run...
However, I just ran a program to test this:
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
int y;
cout << "Enter number of elements of array: ";
cin >> y;
int x[y]; // I declared an array using a variable size instead of a constant expression
x[y-1] = 3;
cout << x[y-1];
return 0;
}
...and there were no errors. So is the statement made by the tutorial incorrect or am I misinterpreting it?
No, they're not.
What you're seeing here is a GNU extension called "variable length arrays" (which are still stack-based).
The quotation is correct in the context of the actual C++ language itself.
If you used proper compilation flags (-Wall -Wextra -pedantic) then your compiler would tell you this.
Your program isn't legal C++. The compiler you are using has an extension to allow you to use a non-constant expression as an array size. Here's what my compiler has to say about it:
main.cpp:10:10: warning: variable length arrays are a C99 feature [-Wvla-extension]
int x[y]; // I declared an array using a variable size instead of a constant expression
^
Furthermore, this has nothing to do with dynamic allocations: your array is still stored on the stack just like any other automatically allocated object.
As others have already stated your compiler is using an extension for this.
When declare array like this ->
int arr[100];
C++ allocates it on stack. To create dynamic array in c++, you have to declare it in following way:
int *arr;
arr = new int[n];
Dynamic arrays are allocated using heap.
You used a compiler that has its own language extension that does not C++ compliant. C++ does not allow Variable Length Arrays as in your program However C does allow to define such arrays. So some C++ compilers include this feature of the C Standard in their C++ grammar.
In C++ the declarator of an array is defined the following way
noptr-declarator [ constant-expressionopt] attribute-specifier-seqopt
while in C it is defined according to the following grammar rule
direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
So the language extension of your compiler uses the definition of the array declarator similar to the C definition of the array declarator.
I am new to C++.I was going through a C++ book and it says
const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // Illegal
It says the declaration of the float variable is invalid during compilation.Why is that?
Suppose if we use
int i = 3;
float f[i];
It works.
What is the problem with the first situation?
Thanks.
So the first is illegal because an array must have a compile-time known bound, and i[3], while strictly speaking known at compile time, does not fulfill the criteria the language sets for "compile-time known".
The second is also illegal for the same reason.
Both cases, however, will generally be accepted by GCC because it supports C99-style runtime-sized arrays as an extension in C++. Pass the -pedantic flag to GCC to make it complain.
Edit: The C++ standard term is "integral constant expression", and things qualifying as such are described in detail in section 5.19 of the standard. The exact rules are non-trivial and C++11 has a much wider range of things that qualify due to constexpr, but in C++98, the list of legal things is, roughly:
integer literals
simple expressions involving only constants
non-type template parameters of integral type
variables of integral type declared as const and initialized with a constant expression
Your second example doesn't work and it shouldn't work.
i must be constant. This works
const int i = 3;
float f[i];
Just to expound on Sebastian's answer:
When you create a static array, the compiler must know how much space it needs to reserve. That means the array size must be known at compile-time. In other words, it must be a literal or a constant:
const int SIZE = 3;
int arr[SIZE]; // ok
int arr[3]; // also ok
int size = 3;
int arr[size]; // Not OK
Since the value of size could be different by the time the array is created, the oompiler won't know how much space to reserve for the array. If you declare it as const, it knows the value will not change, and can reserve the proper amount of space.
If you need an array of a variable size, you will need to create it dynamically using new (and make sure to clean it up with delete when you are done with it).
For arrays with lengths known only at runtime in C++ we have std::vector<T>. For builtin arrays the size must be known at compile-time. This is also true for C++11, although the much older C99-standard already supports dynamic stack arrays. See also the accepted answer of Why doesn't C++ support dynamic arrays on the stack?
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.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Why this code doesn't compile
#include <stdio.h>
int x=5;
int a[x];
int main()
{
a[0]=5;
printf("%d\n",a[0]);
return 0;
}
When compiled with gcc filename.c -Wall -ansi -pedantic it produces a error
error: variably modified ‘a’ at file scope
However this code compiles although giving warnings but gives correct output:
#include <stdio.h>
int main()
{
int x=5;
int a[x];
a[0]=5;
printf("%d\n",a[0]);
return 0;
}
warning: ISO C90 forbids variable length array ‘a’ [-Wvla]
However if i try to compile this using g++ filename.c -Wall -ansi -pedantic it produces no warnings and gives correct output too
#include <stdio.h>
const int x=5;
int a[x];
int main()
{
a[0]=5;
printf("%d\n",a[0]);
return 0;
}
I am using gcc version 4.7.0
Please explain in detail what's happening ?
In C(unlike C++) const declarations do not produce constant expressions, i.e. in C you can't use a const int object as array size in a non-VLA array declaration.
So,
const int max_foos = 10;
int foos[max_foos];
is valid in C++ but invalid in C. Equivalent C code will be:
#define MAX_FOOS 10
int foos[MAX_FOOS];
Note that:
const in c doesn't mean constant. It means "read only".
Note variable length arrays became a part of the C standard only in C99 prior to that the standard did not allow them though most compilers allowed them as a extension.
The first code snippet doesn't compile because the array subscript needs be a constant which it is not. Also, variable length arrays cannot be declared at global scope.
The second code snippet doesn't compile because variable length arrays were not part of standard prior to c99.
The third snippet compiles because const declarations produce constant expressions in C++ unlike C.
In C only array objects with automatic storage duration can be variable length arrays. Object declared at file scope cannot have automatic storage duration.
In your second code example, c89/c90 does not have variable length arrays and you have to use a c99 compiler to use the feature. If you are using gcc you can select c99 with option -std=c99. Or you can use the last version of c: c11.
C++ does not have variable length arrays.
Variable length arrays are supported only since C99 and they can't be global:
C11, Array Declarators, 6.7.6.2:
If an identifier is declared as having a variably modified type, it
shall be an ordinary identifier (as defined in 6.2.3), have no
linkage, and have either block scope or function prototype scope. If
an identifier is declared to be an object with static or thread
storage duration, it shall not have a variable length array type.
Yes, and ?
Different generations of C and C++ have different rules for what you can use to size an array. In the first case, you are compiling to classic ANSI (C89/90).
C++ allows (constants) to be used as array sizes, as does C99. Note that the "original" C++ ANSI standard is newer than 1990, so it has a lot of the things added in the C99 standard.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is there a way to initialize an array with non-constant variables? (C++)
I have the following code:
vector<vector<vec2>> vinciP;
int myLines = -1;
myLines = drawPolyLineFile("vinci.dat", vinciP);
if (myLines > -1)
{
cout << "\n\nSUCCESS";
vec2 vPoints[myLines];
for (int i = 0; i < NumPoints; ++i)
{
vPoints[i] = vinciP[0][i];
}
}
I'm getting an error on the line 'vec2 vPoints[myLines];' that says expressions must have a constant value. I don't understand why I'm getting this error, any help?
Is it because myLines could be negative? idk.
vec2 vPoints[myLines];
Since myLines is not a const expression ((which means, it is not known at compile-time), so the above code declares a variable length array which is not allowed in C++. Only C99 has this feature. Your compiler might have this as an extension (but that is not Standard C++).
The solution to such commom problem is : use std::vector<T> as:
std::vector<vec2> vPoints(myLines);
It should work now.
Is it because myLines could be negative?
No, It is because myLines is not a compile time constant.
Explanation:
vec2 vPoints[myLines];
Creates an array of variable length, where myLines value will be determined at Run-time.
Variable length arrays are not allowed in C++. It was a feature introduced in C99, and C++ Standard does not support it. Some C++ compilers support it as an extension though but it is nevertheless non standard conforming.
For C++ size of an array should be known at compile time and hence must be compile time constant. myLines is not a compile time constant and hence the error.
You should use a std::vector
vec2 vPoints[myLines];
Array size must be a compile time constant. myLines is not a compile time constant. Instead, allocate the memory using new or even better to use std::vector.
C++ does not have variable-length arrays. The size of an array must be determined at compile-time. The value of myLines is only known at runtime, so this won't work.
To have arrays whose size is only known at runtime, use std::vector.
std::vector<vec2> vPoints(myLines);
You are getting that error because static arrays need a static (constant) size. Since the number of components in your vPoints is dynamic, consider using a dynamic array instead. Or better yet stick with vector.