gcc runtime declaration of static and auto variables [duplicate] - c++

This question already has answers here:
Why can't the size of a static array be made variable?
(4 answers)
Closed 8 years ago.
I am compiling my C code using the gcc compiler
My code is
main()
{
int i;
scanf("%d",&i);
int a[i];
}
... and it executes it without any warning. However, if I use:
main()
{
int i;
scanf("%d",&i);
static int a[i];
}
... I get an error message saying the size of array is not constant.
If execution of program starts at main function it should not give such error.
and if static data is allocated first before start of main(), how is the compiler able to generate such errors during during compile time?

Variables length arrays are not allowed to be static from the draft C99 standard section 6.7.5.2 Array declarators paragraph 2 says (emphasis mine):
An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have
either block scope and no linkage or function prototype scope. If an identifier is declared to be an object with static storage duration, it shall not have a variable length array type.
In C++ variable length arrays are not part of the standard and are a compiler extension but gcc should be be following the C99 rules there as well.

Related

Dynamically initializing a static value in C vs C++ [duplicate]

This question already has answers here:
Difference between initialization of static variables in C and C++
(3 answers)
Closed 3 years ago.
#include <stdio.h>
int b(){
return 5;
}
int main(){
static int a = b();
return 0;
}
Above code doesn't compile in C with this error:
error: initializer element is not a compile-time constant
but compiles fine in C++. What are the differences between initializing static values in C and C++?
From cppreference:
Variables declared at block scope with the specifier static or thread_local (since C++11) have static or thread (since C++11) storage duration but are initialized the first time control passes through their declaration (unless their initialization is zero- or constant-initialization, which can be performed before the block is first entered). On all further calls, the declaration is skipped.
So, in C static is initialized at startup, while in C++ during the first time the code passes through this section of code.
This will allow assignment of a return from a function in C++ which would be impossible in C since C would need to know the value before the program starts to run...
I hope this helps
Lior

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.

Are arrays not dynamically allocated in C++? [duplicate]

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.

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.

Unusual behaviour [closed]

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.