C++: Why does int array[size] work? - c++

I have started learning c++. I read that an array's size can only be set before run and dymanic arrays can be set during runtime. So I was expecting this to fail but it didn't:
#include <iostream>
int main() {
using namespace std;
int size;
cout << "enter array size:";
cin >> size;
int i, score[size], max; //array size set to variable doesn't fail
cout << endl << "enter scores:\n";
cin >> score[0];
max = score[0];
for (i = 1; i < size; i++)
{
cin >> score[i];
if (score[i] > max)
max = score[i];
}
cout << "the highest score is " << max << endl;
return 0;
}
Is this a new feature in recent C++ compilers? Is it realising I need a dynamic array and creating that instead?

Probably you are using GCC compiler, it has an extension called Arrays of Variable Length.
std::vector is the real dynamic arrays in C++.
To select this standard in GCC, use the option -std=c++11; to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if you want them to be errors rather than warnings).

In all current and past standards, that code is ill-formed. Variable Length Arrays are a C99 feature not a C++ feature, although some compilers do provide it as an extension. In the upcoming standard (expected to be C++14, currently in the process of review) a similar feature by other name (and slightly different semantics) has been adopted, so expect this to become standard in the future.
Note that in general, that is, excluding arrays of runtime bound (as they are named in the upcoming standard), the size of the array is part of the static type of the object and known at compile time. In the case of VLAs or array of runtime bound, the size is not known at compile time and thus the type is somehow of a second class citizen among types. The implication is that you cannot use VLAs/ARB with templates (as code generation for the template depends on the type, which includes the size, which is unknown at compile time).
In the same way there are other limitations, sizeof is not a compile time operation for VLAs, and it is not even allowed for ARB, these form of arrays can only be used for objects with automatic storage duration (i.e. in the stack), you cannot take the address of the array (although you can take the address of the first member),...
Another important point to consider is that the standard does not guarantee that the memory for an ARB will be allocated on the stack, and allows implementations to call a global allocation function, although the intention is that compilers will catch up and provide the space from the stack.

Be careful! Undefined integers are not guarenteed to be any value at all. Some compilers will default to 0, while others will use whatever garbage bits where already in memory. For this reason Visual Studio wouldn't even let me compile. Step through your code to see the allocated memory for score before you set the size variable. Likely size as it is compiled is a random integer from garbage memory, which means it can change every time you execute!
A C style array needs to know how much continuous memory to allocate. This allows for direct indexing, and other optimizations. As others have suggested, std::vector is what is the standard dynamic container in C++, which uses an array under the hood.

Related

C++ examples where dynamic array is required instead of static array

I am trying to understand the difference between static and dynamic arrays in C++ and I can not think of a case where a static array would not do the trick.
I am considering a static array that would be declared this way:
int N=10;
int arr[N];`
I read here that the main difference between static and dynamic array is that a static array is allocated during compilation so N needs to be know at compilation.
However, this explains that arrays declared this way can also be Variable-length arrays:
Variable-length arrays were added in C99 - they behave mostly like fixed-length arrays, except that their size is established at run time; N does not have to be a compile-time constant expression:`
and indeed, the following c++ code is working, even though n is only known at runtime :
int n =-1;
std::cin>>n;
int arr[n];
//Let the user fill the array
for(int i=0; i<n;i++){
std::cin>>arr[i];
}
//Display array
for(int i=0; i<n;i++){
std::cout<<i<<" "<<arr[i]<<std::endl;
}
So I would like an example of code were a static arrays defined like this would not work and the use of dynamic array would be required ?
The code doesn't work on all compilers because variable length arrays aren't part of C++. They are part of C as of ISO C99, and some compilers will allow VLAs in C++, but it's not a portable solution. GCC, for instance, allows VLAs, but warns the user (-Wno-vla).
Below the hood, VLAs are dynamic anyway as the compiler can't reserve the appropriate amount of stack memory because it doesn't know how big the array is going to be. Instead of VLAs, std::vector can be used for dynamic memory that gets deallocated at the end of the scope.

Allocating arrays in C++ [duplicate]

This question already has answers here:
In C++ books, array bound must be constant expression, but why the following code works?
(2 answers)
Closed 9 years ago.
When I started programming with C++ I was learned to allocate the array size by using dynamic memory allocation as follows:
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
int *nArray = new int[nArrayLength];
// contents
delete[] nArray;
return 0;
}
Now I tried the following code using Code::Blocks 12.11 with the mingw32-g++ // GNU GCC compiler.
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
int nArray[nArrayLength];
return 0;
}
This also works fine.
Therefore, why should I use dynamic memory allocation in this case when the easier method also works fine?
You should use neither.
The first is valid, but it's C-style code. The second is non-standard code - it's accepted by that compiler because of some extension.
Use a std::vector instead:
#include <vector>
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
std::vector<int> nArray(nArrayLength);
return 0;
}
A vector has the same semantics as an array, it can grow dynamically (and automatically), and does all the pesky memory management under the hood.
The second code is not valid standard C++. It uses a compiler extension called variable length arrays. See the GCC documentation.
However, there is a proposal for variable length arrays with automatic storage duration that has been adopted for C++14.
Compile the second code with -pedantic option if you're using GCC. It would not compile.
It is because it is not Standard conformant. Variable Length Array (VLA) is not in the Standard C++. It is a compiler extension.
Sometimes you don't know the size of your array beforehand, so you need to allocate storage for it that may grow or shrink dynamically. You should use std::vector because it manages the array storage transparently.
If you are forced to use C-style arrays, use them like in the first code snippet, the second one is not standard C++.
It depends whether you want to use the stack or the heap.
You can also use auto_ptr if you want your heap allocation to be released automatically when scope goes out.

Dynamic allocation

Is it possible to mimic the behavior of dynamic allocation using the following code. For example we do not know the exact number of the integer that are stored in a file and we are going to read the file and then store it in an array called Hello.
int x;
int n=0;
ifstream input("a.dat");
while (!input.eof())
{
input >> x;
n++;
}
input.close();
int Hello[n];
cout << "n= " << n << endl;
int i=0;
while (!input.eof())
{
input >> Hello[i];
i++;
}
Is it possible to mimic the behavior of dynamic allocation using the
following code.
No, the major difference is that the array in your program is stored on stack, whereas all dynamic memory allocations takes place on heap.
What you are exactly doing, in your code is using the VLA feature of C99 standard of C in C++. Compiling with the -pedantic option in g++ compiler will reveal this. Since it is not directly supported by c++, and it is a implementation-specific language extension, its not such a good idea to use it, if you aim to write portable code.
VLA's use alloca() , to allocate memory on stack at runtime, and the disadvantages of such a tecnnique are discussed here.
Further more, VLA's allocate memory on stack during runtime, and if the value exceeds the range, the program simply crashes, while it is ok to quickly create a few bytes of array using VLA's , creating uncertain amounts of large memory may not be safe, and it is best to handle it using dynamic memory allocation.
int Hello[n];
is NOT dynamic allocation. It is required that n is a compile time constant if you want to declare Hello in this way.
try:
int* Hello = new int[n];
and don't forget to release the memory when you are done using it:
delete[] Hello;
This is allowed as an extension by some compilers, but is not strictly part of C++.
int Hello[n];
As an alternative, you can allocate the memory yourself:
int* Hello = new int[n];
And free it yourself also:
delete[] Hello;
But you can avoid manual memory management by usng std::vector from <vector>. One of its constructors accepts an initial size:
vector<int> Hello(n); // Vector with n elements, all initially 0.
You can also set an initial capacity without resizing, to do the allocation once:
vector<int> Hello; // Empty vector.
Hello.reserve(n); // Allocate space for n elements; size() is still 0.
Then read into an int and use push_back to insert values:
int value;
while (input >> value)
Hello.push_back(value);
Note the use of input >> value as the loop condition—this reads as long as reads are successful. eof() returns true only when the last read operation failed due to unexpected end of file, which is unlikely to be exactly what you want.
For a start the second
while (!input.eof())
Will always fail. That terminated the first one and then you set about closing that input stream!

Creating static array in c++ at run time

Is there any way of creating a static array in c++ at run time.
What i want is really simple like just want to get input number from user and create a static array of size of input number at run time. No new operator is required no pointer are required just static array?
No. static variable is allocated before the program code is actually running (i.e.: before your main is called). What you need is a dynamic (aka created at run time) array. If you want to avoid new you can create it on stack (by passing parameter to a function that will create it and working on it within that function), but that's not the same as static. You can also use template containers that will do the allocation and resizing for you (like std::vector, mentioned in other answers)
edit
It seems to bother some people that I didn't mention the matter of initializing static objects. Although not directly relevant to the question - worth to know that static member variables or static variables within a scope can be initialized at run time, but the space for them is reserved prior to the main, so the size of the variable cannot be changed.
If you mean
unsigned size;
std::cin >> size;
int arr[size];
Then: No. C99 has a feature called Variable-Length-Arrays, but the C++03 (and '0x) standard have no notion of this kind of feature.
Use alloca to allocate space on the stack, just like a static array or like a C99 variable length array.
#include <iostream>
#include <alloca.h>
int main() {
unsigned sz;
std :: cin >> sz;
int * p = static_cast<int*>(alloca(sz * sizeof(int)));
// do stuff with p, do not attempt to free() it
}
I've only ever used it with C, but it works well. Read about it first though. It probably isn't very portable.
No.
By definition, you need to dynamically allocate anything whose size is not known until runtime. That's why new and friends exist.
What does it mean to you that an array is static? What advantages do you think it gives you?
Actually, any static variable (including arrays) has its storage reserved at the beginning of the program. For this reason, its size has to be known before the program starts running, so it can't depend on user input in any way.
There are a number of ways to make dynamic non-static arrays, however, so let us know what you're trying to do.
It sounds like what you want is an array whose size is run-time defined but whose life time is defined by static storage duration (ie the length of the program).
You can not use the basic array built into the language. The size of these objects are defined at compile time and can not be modified at run-time. But there are a couple of alternatives.
The basic std::vector is probably what you want:
std::vector<int> data;
int main()
{
int size;
std::cout << "Input the size of the array\n";
std::cin >> size;
// This line sets the size of the container
// vector is basically a C++ wrapper around a dynamically sized array
data.resize(size);
// Now we can safely read values into the array (like) container.
for(int loop =0;loop < size;++loop)
{
std::cout << "Input Value " << loop << "\n";
std::cin >> data[loop];
}
}

Global Arrays in C++

Why the array is not overflowed (e.g. error alert) when the array is declared globally, in other why I'm able to fill it with unlimited amount of elements (through for) even it's limited by size in declaration and it does alert when I declare the array locally inside the main ?
char name[9];
int main(){
int i;
for( int i=0; i<18; ++i){
cin>>name[i];
}
cout<<"Inside the array: ";
for(i=0; i<20; i++)
cout<<name[i];
return 0;
}
C++ does not check bounds errors for arrays of any kind. Reading or writing outside of the array bounds causes what is known as "undefined behaviour", which means anything could happen. In your case, it seems that what happens is that it appears to work, but the program will still be in an invalid state.
If you want bounds checking, use a std::vector and its at() member function:
vector <int> a( 3 ); // vector of 3 ints
int n = a.at( 0 ); // ok
n = a.at( 42 ); // throws an exception
C++ does not have array bounds checking so the language never check to see if you have exceeded the end of your array but as others have mentioned bad things can be expected to happen.
Global variables exists in the static segment which is totally separate from your stack. It also does not contain important information like return addresses. When you exceed an array's boundaries you are effectively corrupting memory. It just so happens that corrupting the stack is more likely to cause more visible bad things than corrupting the data segment. All of this depends on the way your operating system organizes a process's memory.
its undefined behavior. Anything can happen.
You cannot assume too much about the memory layout of variables. It may run on your computer with these parameters, but totally fail when you increase your access bounds, or run that code on another machine. So if you seriously want to write code, don't let this become a habit.
I'd go one step further and state that C/C++ do not have arrays. What they have is array-like syntactic sugar that is immediately translated to pointer arithmetic, which cannot be checked, as pointers can be used to access potentially all of memory. Any checking that the compiler may manage to perform based on static sizes and constant bounds on an index is a happy accident, but you cannot rely on it.
Here's an oddity that stunned me when I first saw it:
int a[10], i;
i = 5;
a[i] = 42; // Looks normal.
5[a] = 37; // But what's this???
std::cout << "Array element = " << a[i] << std::endl;
But the odd-looking line is perfectly legal C++. This example emphasizes that arrays in C/C++ are a fiction.
Neil Butterworth already commented on the benefits of using std::vector and the at() access method for it, and I cannot second his recommendation strongly enough. (Unfortunately, the designers of STL blew a golden opportunity to make checked access the [] operators, with the at() methods the unchecked operators. This has probably cost the C++ programming community millions of hours and millions of dollars, and will continue to do so.)