This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 8 years ago.
int n=5;
int arr[n];
I want to declare size of array as above in C++, but I get error while compiling. I find a lot of code in internet which uses these type of declaration instead of simple putting int arr[5]. How come the code compiles successfully for them but not for me. P.S: I use windows7 and Visual Studio(IDE).
Error Message : Expresion must have a constant value
The number of elements of the array, the array bound, must be a constant expression.
You have to use
const int n = 5;
or
constexpr int n = 5;
else it is a non standard extension : variable length array (VLA).
The error message actually describes rather well what’s going on: C++ does not support arrays with a non-constant size (more precisely, the size needs to be known at compile time).
There are two solutions for this:
If the size is actually a constant, declare it as constexpr (if you can’t use C++11, you can also use const):
constexpr int n = 5;
std::array<int, n> arr;
Which requires the standard header <array>. Or, if you cannot use C++11, change the second line to
int arr[n];
If the size isn’t known at compile time, don’t use a static array, use a dynamic container instead:
int n = 5;
std::vector<int> arr(n);
This requires the <vector> standard header.
Related
This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Why a const size is needed in an array?
(1 answer)
Closed 4 months ago.
I want to convert a float vector to a float array in C++ 20. I searched online and found this solution:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> input({ 1, 2, 3, 4, 5 });
int arr[input.size()];
std::copy(input.begin(), input.end(), arr);
for (int i: arr) {
std::cout << i << ' ';
}
return 0;
}
But when I try to implement it, the compiler gives me an error saying that what's inside the brackets in the array declaration must be a constant expression.
Since when is this the case? I swear I've declared arrays in a similar manner in C++ before and it worked. And if you look online you'll see that everyone does this too, the example I posted seems to be the standard solution to my problem. So why does it give me an error?
Since when is this the case?
Since always. In standard C++, you cannot allocate a block of memory on the stack if you don't know its size at compile time.
Some compilers allow it as an extension. It's also standard in C99, and these arrays are then known as variable-length array.
A lot of what you see online is non standard. Just because someone does something that works for them doesn't mean it will work for you. In this case, it can certainly work for you if you don't care about writing cross-platform, standard compliant code. But if you want to write standard compliant code, you have basically two choices: make an array with a large enough size, known at compile time, and only use part of it, or don't use an array.
To address your comment:
Because a third party function (OpenGL) requires an array as an argument.
No function requires an array as argument. It can require a raw block of memory, but then you also need to give it the size of that block. You can easily do that with a std::vector, using the methods data() and size().
The only way I know of to require an array as argument is through some template magic:
template<std::size_t N>
void print_size(int (&array)[N]) {
std::cout << N;
}
Demo
Even then, you can apparently pass it a vector if you specify the size (might be undefined behavior):
std::vector<int> v = {1, 2, 3};
print_size<3>(reinterpret_cast<int(&)[3]>(*v.data()));
In C++ I tried declaring a global array of some size. I got the error:
array bound is not an integer constant before ‘]’ token
But when I declared an array of the same type in the main() function it is working fine.
Why is there different behaviour here?
int y=5;
int arr[y]; //When I comment this line it works fine
int main()
{
int x=5;
int arr2[x]; // This line doesn't show any error.
}
Edit: Many are suggesting this question is a duplicate of Getting error "array bound is not an integer constant before ']' token". But that question doesn't answer why there is different behaviour.
Both examples are ill-formed in C++. If a compiler does not diagnose the latter, then it does not conform to the standard.
Why there is a different behaviour here?
You use a language extension that allows runtime length automatic arrays. But does not allow runtime length static arrays. Global arrays have static storage.
In case you are using GCC, you can ask it to conform to the standard by using the -pedantic command line option. It is a good idea to do so in order to be informed about portability problems.
The size of an array must be a constant. You can fix this by declaring y as const.
const int y=5;
int arr[y];
As for why this worked in main, g++ does allow a variable length array in block scope as an extension. It is not standard C++ however.
Both shouldn't be used, one works because (as #eerorika said) automatic length arrays are allowed on runtime, but global arrays need to have static storage.
If you want to declare an array with a variable size (e.g. given by std::cin) you would do something along the lines of:
int x;
std::cin >> x;
const int n = x;
float arr[n];
But you wouldn't be able to set it to contain just zeros with float arr[n] = {0} (if you need to add to a value in the array, not being sure you set it), you would need to use a loop like that
for(int i = 0; i < n; i++)
{
arr[i] = 0;
}
The type-system of C++ handles these C-like arrays in a way that it defines arr2 from your example of type int[5]. So, yes the number of elements of the array is part of the type!
This puts some constraints on what you are allowed to use in the definition of C-like arrays. I.e. this number needs to have static storage, needs to be immutable and needs to be available at compile time.
So, you might want to change your code to something like the following, which will have another goodie. It initializes the array in a proper way:
int arr2[] = {0, 0, 0, 0, 0};
This question already has answers here:
local variable as a non-typename argument
(2 answers)
Closed 4 years ago.
I know I can use a vector, but I don't need the extra features of a vector so wanted to use a std::array. The problem I have is that I get the size of the array from the user - from stdin. Then I know the size and initialise the array from there.
I tried the following code but get the compiler error as shown. I also tried constexpr with fsize.
How can I edit my code to create a std::array from a size not known at compile time?
int main() {
int size;
cin >> size;
const int fsize = size;
// below line compile error
std::array<int, fsize> items;
}
compile error:
error C2971: 'std::array' : template parameter '_Size' : 'fsize' : a local variable cannot be used as a non-type argument
: see declaration of 'std::array'
see declaration of 'fsize'
How can I edit my code to create a std::array from a size not known at compile time?
You can't. std::array is a fixed-sized array, it's size must be a constant known at compile-time.
To make a dynamic array whose size is not known until runtime, you must use new[] instead:
int *items = new int[fsize];
...
delete[] items;
Preferably, you should use std::vector instead, which handles that for you:
std::vector<int> items(fsize);
If you don't want to use std::vector, you can use std::unique_ptr<int[]> instead:
std::unique_ptr<int[]> items(new int[fsize]);
or
auto items = std::make_unique<int[]>(fsize);
This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 16 days ago.
void method(string a) {
int n = a.size();
int array[n];
}
The above code can compile correctly using gcc. How can the size of the array come from a non-constant variable? Does the compiler automatically translate the int array[n] to int* array = new int[n]?
How can the size of the array come from a non-constant variable?
Currently, because that compiler has a non-standard extension which allows you to use C's variable length arrays in C++ programs.
Does the compiler automatically translate the int array[n] to int* array = new int[n]?
That's an implementation detail. I believe GCC places it on the stack, like normal automatic variables. It may or may not use dynamic allocation if the size is too large for the stack; I don't know myself.
dynamic allocation. The new keyword will do this with a pointer and some allocation.
int * ptr;
int n = a.size();
ptr = new int[n];
According to this the compiler allows this expression in C++ as far as C90/99.
This question already has answers here:
In C++ books, array bound must be constant expression, but why the following code works?
(2 answers)
Closed 5 years ago.
As C++ primer said, we can't use variable as the dimension of builtin array, so the following code did not work
int length = 3;
int array[length] = {0, 1, 2};
the error is
error: variable-sized object may not be initialized
But why following code works?
int length = 3;
int array[length];
This is an extension by your compiler called a Variable Length Array (VLA) and is not in the C++ standard which means that this code can break at any moment you switch compilers or the compiler vendor decides to no longer support this feature. If you want a variable length array that does not depend on this extension but instead on the standard you should use a std::vector.