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

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.

Related

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.

Expected constant in 2d array

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?

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.

dyanamic allocation on stack on run time

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++.