Global - Local difference in the init of an array in c - c++

Why this dont work:
int size = 2;
int array[size];
int main() {
return 0;
}
It says the error: array bound is not an integer constant
And this work:
int size = 2;
int main() {
int array[size];
return 0;
}
Anyone knows the reason?
thanks

In C++ or C89/90 neither works. These languages require that array size is an Integral Constant Expression (ICE). In your examples size is not an ICE. If your C++ or C89/90 compiler allows it, it is nothing else than a non-standard compiler extension.
In C99 the second works because this is how Variable Array Length (VLA) specification is defined. VLA can only be defined in local scope.

Dynamic sized arrays is a feature of C99 and is not included in the current C++ standard at all.
If you are compiling as C++ neither should work. If you change to a const variable then both methods will be allowed by the C++ standard.

Related

Run time C++ array initialization question

Why can't we initialize array size using non-const size in global area....outside main() ....
//outside main - global
int val=5;
int arr[val];
int main()
{
}
this gives error
7:12: error: array bound is not an integer constant before ']' token
In function 'int main()':
But if i move this same code inside main/body of function error disappears....
there is no error and it compiles fine...
int main()
{
int val=5;
int arr[val];
}
Also this works fine inside body of a function
void fn(int val)
{
int arr[val];
}
int main()
{
fn(5);
}
Confused and how does moving array size can't be intialized only outside main?
The first sample, at file scope
int val=5;
int arr[val];
int main()
is illegal on both C and C++. Variables at file scope must be defined (created) before their first use, and continue to exist until the program ends - which also means that, once created, an array cannot be resized. In the case of arrays, this means (among other things) that their dimension must be known at compile time. Using a variable as an array dimension runs afoul of the need for the size of a static to be known at compile time - for example, the value of val could be changed at run time (e.g. in main()) which will be AFTER arr is created.
The second example
void fn(int val)
{
int arr[val];
}
is legal in C (from 1999), because arr is of automatic (not static) storage duration. It will be created when the function body is entered, and cease to exist when the function returns. This is called a "variable length array" or VLA, because the number of elements is determined by a value of a variable (val) at run time.
VLAs were also not supported before the 1999 C standard.
In C++, VLAs are illegal. Period. However, some C++ compilers do support such a feature as a non-standard extension. In C++, rather than using arrays, a standard container (e.g. std::vector<int>) is preferred for various reasons, including ability to resize it at run time.
For the array inside function:
you are relying on GCC extension, if you add -pedantic you will get this warning:
warning: ISO C++ forbids variable length array 'arr' [-Wvla]
So C++ does not support variable length arrays, suggested alternative is std::vector.
For the array outside function:
you need to add const before int. Yes I know compiler could in theory figure out that val is never changed, but for some reason(nobody thought to add that to standard, or there are good reasons not to do it) you are required to add const.

Can size of an array be determined at runtime? [duplicate]

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.

usage of const in c++

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?

Declare array with declared constant

I'm trying to do something like this:
const int array_size = 5;
string stuff[array_size];
My compiler won't let me compile this, even though array_size is a constant. Is there a way to do this without dealing with dynamic arrays?
Edit: "error C2057: expected constant expression"
I have answered this question assuming you are either coding in C or C++. If you are using a different language, this answer doesn't apply. However, you should update your question with the language you are trying to use.
Consider the following program:
int main () {
const int size = 5;
int x[size];
return 0;
}
This will compile in both C++ and C.99, but not C.89. In C.99, variable length arrays were introduced, and so locally scoped arrays can take on a size specified by a variable. However, arrays at file scope in C.99 cannot take a variable size parameter, and in C.89, all array definitions have to have a non variable size.
If you are using C.89, or defining a file scope array in C.99, you can use an enum to name your constant value. The enum can then be used to size the array definition. This is not necessary for C++ however, which allows a const integer type initialized by a literal to be used to size an array declaration.
enum { size = 5 };
int x[size];
int main () { return 0; }
#define array_size 5
string stuff[array_size];
You can use e.g. a vector or the new keyword to allocate memory dynamically, because declared arrays can not have runtime sizes.
Only thing I can think of is that you defined another array_size variable in your code, which is not a compile time constant and hides the original array_size.
array_size is not treated as a compile time constant. Constness added just makes sure that programmer can not modify it. If tried to modify accidentally, compiler will bring to your attention.
Size of an array needs to be a compile constant. Seems like your compiler is not supporting Variable Length Array. You can #define the size of the array instead which is treated as a constant expression.

Variable length arrays (VLA) in C and C++

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.