Non-const declaration of array - c++

I have been teaching myself programming for couple of years, and I was sure that if you need array declaration of a variable number you need to use malloc or new.
Today I found that this compiles under g++ version 4.4.4, without warnings or errors:
#include <iostream>
using namespace std;
int main()
{
int size_array;
cin >> size_array;
int iTable[size_array];
for(int i=0;i < size_array;i++)
iTable[i]=i*i;
for(int i=0;i < size_array;i++)
cout << iTable[i] << endl;
return 0;
}
Also it compiles completely fine if you are using gcc (after changing cout and cin with printf and scanf)
Under Visual Studio this code fails to compile since size_array is not constant.
When this was changed? This is a safe method?

This is a C99 feature - VLA - which is not a part of standard c++. You can use it if your compiler supports it and you don't require portability. If the compiler supports it, it's perfectly safe to use - but it's a bad habit using non-standard features.

This is a compiler extension of gcc, not standard.

No thats not safe at all. It could corrupt your stack.

See http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.20.
Simply put, in C99, this is called VLA and is part of the standard (correct me if I'm wrong) but in C++ this is not part of the standard. If you need this functionality use std:vector instead.

This depends if you are writing C or C++. I'll assume C as for c++ you would be better off using std::vector rather than an array.
In C it depends which versiuon you are using. If and only if you are using a C99 standard compiler then the array can take its size from a variable at run time as you do here otherwise the size must be defined at compile time. Visual Studio does not support the dynamic array - see MSDN
C++ uses the C89 standard so requires the size to be set at compile time.
So in your case you need to see what flags you passed to the compiler.
As noted by #Eric the code is C++ so the working compiler is using a non standard extention so for gnu I would add flags to enforce a standard e.g. -ansi or -std=c++98 and -pedantic

There is an extension of GCC mimicking C99 Variable Length Arrays. It's not standard C++.
However, even if you have this turned off, the posted code can compile. The standard does not require a diagnostic for this case: it's Undefined Behaviour, not an error.
In really obvious cases a compiler may choose to prevent you from writing this, but otherwise it is free to let you fail in peace.
Conclusion: don't be fooled by the compilation. It's still bad and wrong.

You can get this functionality in C or C++ with alloca (_alloca on Windows). std::vector is NOT a substitute: it is allocated on the heap, with new, which calls malloc, which is potentially expensive.
There is a good reason why you might want to have an array whose length is determined at runtime allocated on the stack: it's really fast. Suppose you have loop that executes frequently but has an array that depends on something at runtime (say, the size of your canvas widget). You can't just hard-code a number: your program will crash when we all get 36" 300 dpi Retina-display monitors and pixels[2400] is no longer safe. But you don't want new, or your loop hits a malloc and gets slow.
Although, for large arrays, it might be better to have a std::vector that is static to the function an only gets resized (larger) when necessary since your stack has limited size.
(See http://msdn.microsoft.com/en-us/library/wb1s57t5(VS.71).aspx)

It's okay to use the feature if you are using c99.
You have to be very careful about the value of size. a large value will overflow your stack, and your process may go insane.

Related

Why is it allowed to declare an automatic array with size depending on user input? [duplicate]

This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 4 years ago.
I'm using MinGW to compile for C++11 and I found out that this doesn't throw an error:
int S;
cin>>S;
char array[S];
While this does ("storage size of 'array' isn't known"):
char array[];
To me, the size is also unknown in the first case, as it depends on what the user input is.
As far as I knew, automatic arrays are allocated at compile time in stack memory. So why wouldn't the first example fail?
It's not. C++ doesn't have variable-length arrays, though some compilers allow it as an extension of the language.
You are apparently not aware of the GNU GCC extension Arrays of Variable Length. Therefore your first code compiles.
The error message is something different. You have to specify the array length.
gcc has the -pedantic switch - enabling this switch the compiler will report your first code as invalid:
warning: ISO C++ forbids variable length array ‘array’
Read also this thread What is the purpose of using -pedantic in GCC/G++ compiler?
Use very carefully compiler extensions because should you port your code to another compiler then you are in big trouble.
[This answers the original version of the question which asked about a static array; Deduplicator corrected this misconception, but now the question is missing a part.]
If your assumption that this piece of code defined a static array were correct, you'd be wondering for a good reason indeed: Something that is determined at compile time, like data with static storage duration, can obviously not depend on user input at run time. This truism is independent of any specific language.
The array defined in your code snippet has, by contrast, automatic storage duration, vulgo is created on the stack. A complete minimal working example would have made the case clearer: It would have shown that the code is in a function.
Objects with automatic storage duration can be created as needed at run time; there is no logical problem preventing that, which should fix your general headache ;-).
But note that, as some programmer dude correctly remarked, standard C++ nevertheless does not permit the definition of arrays whose size is not known at compile time; standard C does though, since C99. The rationale for C++ no following that amendment is that C++ provides better means for the use case, like the vector template. gcc, which is the compiler used in MinGW, permits this as an extension (and why not — it's available in the compiler anyway).

Declaring an array using const integer

I was trying to declare an int array in C++ and found this problem. The following code runs fine on g++ compiler but the compilation fails on Visual Studio. I was following Bruce Eckel and found this code.
#include<iostream>
int main()
{
const int j = std::cin.get();
char buf[j];
}
Keeping j just an int would be a problem, that I understand. Since the value of j would be const during the run-time, the program should get compiled. Please correct me if I am wrong anywhere.
Since the value of j would be const during the run-time, the program should get compiled.
No, the const-ness of j is irrelevant here. C++ currently only supports statically-sized C-arrays. Its size must be a compile-time constant.
If you want an array of dynamic size, use std::vector.
The fact that g++ by default compiles this is a bit unfortunate (for compatibility). You should use the -pedantic flag when using g++ to ensure that such compiler extensions aren’t enabled (using compiler extensions of course isn’t bad in itself, but in this case there’s not really any advantage).
You are trying to define buf as a variable-length array. This is a feature of C (not C++) that is supported by g++ as a non-standard extension. Evidently your other compiler does not support it.
I would suggest turning buf into std::vector<char> (or indeed std::string?)
Variable length arrays are C99 feature both gcc and clang supports them as an extension in C++ but Visual Studio never did and even though they recently added support for C99 is it not supported in C++
Since you are developing in C++ unless you have a good reason to not use it then std::vector or std::string should be sufficient.
I had the same problem. It seems very difficult to create an array of which its length is stored as a variable. What I did is create an additional function:
void Class:: initMyArray(const int size) {
myArray = new int[size]
}
Now, you just have to call that function and give it your variable. I'm not sure whether this is a proper solution though (I'm not a C++ expert).

can we give size of static array a variable

hello every one i want to ask that i have read that we can declare dynamic array only by using pointer and using malloc or newlike
int * array = new int[strlen(argv[2])];
but i have wrote
int array[strlen(argv[2])];
it gave me no error
i have read that static array can only be declared by giving constant array size but here i have given a variable size to static array
why is it so thanks
is it safe to use or is there chance that at any latter stages it will make problem i am using gcc linux
What you have is called a variable-length array (VLA), and it is not part of C++, although it is part of C99. Many compilers offer this feature as an extension.
Even the very new C++11 doesn't include VLAs, as the entire concept doesn't fit well into the advanced type system of C++11 (e.g. what is decltype(array)?), and C++ offers out-of-the box library solutions for runtime-sized arrays that are much more powerful (like std::vector).
In GCC, compiling with -std=c++98/c++03/c++0x and -pedantic will give you a warning.
C99 support variable length array, it defines at c99, section 6.7.5.2.
What you have written works in C99. It is a new addition named "variable length arrays". The use of these arrays is often discouraged because there is no interface through which the allocation can fail (malloc can return NULL, but if a VLA cannot be allocated, the program will segfault or worse, behave erratically).
int array[strlen(argv[2])];
It is certainly not valid C++ Standard code, as it is defining a variable length array (VLA) which is not allowed in any version of C++ ISO Standard. It is valid only in C99. And in a non-standard versions of C or C++ implementation. GCC provides VLA as an extension, in C++ as well.
So you're left with first option. But don't worry, you don't even need that, as you have even better option. Use std::vector<int>:
std::vector<int> array(strlen(argv[2]));
Use it.
Some compilers aren't fully C++ standard compliant. What you pointed out is possible in MinGW (iirc), but it's not possible in most other compilers (like Visual C++).
What actually happens behind the scenes is, the compiler changes your code to use dynamically allocated arrays.
I would advice against using this kind of non-standard conveniences.
It is not safe. The stack is limited in size, and allocating from it based on user-input like this has the potential to overflow the stack.
For C++, use std::vector<>.
Others have answered why it "works".

Why is it that an int in C++ that isnt initialized (then used) doesn't return an error?

I am new to C++ (just starting). I come from a Java background and I was trying out the following piece of code that would sum the numbers between 1 and 10 (inclusive) and then print out the sum:
/*
* File: main.cpp
* Author: omarestrella
*
* Created on June 7, 2010, 8:02 PM
*/
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
int sum;
for(int x = 1; x <= 10; x++) {
sum += x;
}
cout << "The sum is: " << sum << endl;
return 0;
}
When I ran it it kept printing 32822 for the sum. I knew the answer was supposed to be 55 and realized that its print the max value for a short (32767) plus 55. Changing
int sum;
to
int sum = 0;
would work (as it should, since the variable needs to be initialized!). Why does this behavior happen, though? Why doesnt the compiler warn you about something like this? I know Java screams at you when something isnt initialized.
Thank you.
Edit:
Im using g++. Here is the output from g++ --version:
Im on Mac OS X and am using g++.
nom24837c:~ omarestrella$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646)
Reading from an uninitialized variable results in undefined behavior and the compiler isn't required to diagnose the error.
Note that most modern compilers will warn you if you attempt to read an uninitialized variable. With gcc you can use the -Wuninitialized flag to enable that warning; Visual C++ will warn even at warning level 1.
Because it's not part of the C++ standard. The variable will just take whatever value is currently sitting in the memory it's assigned. This saves operations which can sometimes be unnecessary because the variable will be assigned a value later.
It's interesting to note and very important for Java/.Net programmers to note when switching to C/C++. A program written in C++ is native and machine-level. It is not running on a VM or a some other sort of framework. It is a collection of raw operations (for the most part). You do not have a virtual machine running in the background checking you variables and catching exceptions or segfaults for you. This is a big difference which can lead to a lot of confusion in the way C++ handles variables and memory, as opposed to Java or a .Net language. Hell, in .Net all your integers are implicitly initialised to 0!
Consider this code fragment:
int x;
if ( some_complicated_condition ) {
x = foo;
} else if ( another_condition ) {
// ...
if ( yet_another_condition ) x = bar;
} else {
return;
}
printf("%d\n",x);
Is x used uninitialized? How do you know? What if there are preconditions to the code?
These are hard questions to answer automatically, and enforcing initialization might be inefficient in some small way.
In point of fact modern compilers do a pretty good job of static analysis and can often tell if a variable is or might be used uninitialized, and they generally warn you in that case (at least if you turn the warning level up high enough). But c++ follows closely on the c tradition of expecting the programmer to know what he or she is doing.
It's how the spec is defined--that uninitialized variables have no guarantee's, and I believe the reason is that it has to do with optimizations (though I may be wrong here...)
Many compilers will warn you, depending on the warning level used. I know by default VC++ 2010 warns for this case.
What compiler are you using? There is surely a warning level you can turn on via command-line switch that would warn you of this. Try compiling with /W3 or /W4 on Windows and you'll get 4700 or 6001.
This is because C++ was designed as a superset of C, to allow easy upgrading of existing code. C works that way because it dates back to the 70s when CPU cycles were rare and precious things, so weren't wasted initialising variables when it might not be necessary (also, programmers were trusted to know that they'd have to do it themselves).
Obviously that wasn't really the case once Java appeared, so they found it a better tradeoff to spend a few CPU cycles to avoid that class of bugs. As others have noted though, modern C or C++ compilers will normally have warnings for this kind of thing.
Because C developers care about speed. Uselessly initializing a variable is a crime against performance.
Detecting an uninitialized variable is a Quality-of-Implementation (QoI) issue. It is not mandatory, since the language standard does not require it.
Most compilers I know will actually warn you about the potential problem with an initialized variable at compile-time. On top of that, compilers like MS Visual Studio 2005 will actually trap the use of an uninitialized variable during run-time in debug builds.
So, what compiler are you using?
Well, it depends on what compiler you use. Use a smart one. :)
http://msdn.microsoft.com/en-us/library/axhfhh6x.aspx
Initialising variables is one of the most important tenets of C/C++. Any types without a constructor should be initialised, period. The reason for compiler not enforcing this is largely historical. It stems from the fact sometimes it's not necessary to init something and it would be wasteful to do so.
These days this sort of optimisation is best left to compiler and it's a good habit to always initialise everything. You can get the compiler to generate a warning for you as others suggested. Also you can make it treat warnings as errors to further simulate javac behaviour.
C++ is not a pure object oriented programming language.
In C++ there is no implicit way of memory management and variable initialization.
If a variable is not initialized in C++ then it may take any value at runtime because the compiler does not understand such internal errors in C++.

Creating array with constant

I was working on a program in Netbeans on Linux using a gcc compiler when, upon switching to Visual C++ on Windows 7, the code failed to compile as Visual C++ says it expected constant expression on several lines. On Netbeans, I simply did something similar to char name[fullName.size()];, while on Visual C++, I tried, among other things,
const int position = fullName.size();
char Name[position];
How can I create a constant to use for the array?
Note: I know about this question, but is there any way I can get this working without using vectors, since that would require a re-write of many parts of the program?
This is not possible in VC++. I know, pretty sad :(
The solutions include:
Create it on the heap
Make it constant
The new C++ standard (C++0x) proposes a 'constant expression' feature to deal with this. For more info, check this out.
In VC++ you can't do runtime declarations of stack array sizes, but you can do stack allocation via _alloca
so this:
const int position = fullName.size();
char Name[position];
becomes this:
const int position = fullName.size();
char * Name = (char*)_alloca(position * sizeof(char));
It's not quite the same thing, but it's as close as you are going to get in VC++.
C++ requires that the size of the array be known at compile time. If you don't mind using a non-standard extension, gcc does allow code like you're doing (note that while it's not standard C++, it is standard in C, as of C99).
I'd also guess that you could use a vector (in this particular place) with less trouble than you believe though -- quite a bit of code that's written for an array can work with a vector with only a re-compile, and little or no rewriting at all.
Your char name[fullName.size()]; is an example of a variable-length array which - as far as I know - are not standardized in C++ so you're at the mercy of the compiler.
[Slightly off-topic they're part of the C99 standard]