I am doing the following for initializing an array in c++
int a;
cin>>a;
float b[a];
This works and compiles in my computer. IS this correct? I thought that we can only do this if a was a const int.
Depends on you definition of "correct".
This is called variable-length array (or just VLA) and it's not officially supported in the current versions of C++ (100% sure for C++03 and before, 99.99% sure for C++11), but it is in C.
Some compilers allow this as a compiler extension.
It's not about whether a is a constant int. It's about whether a has a initial value assigned at comipling time. Compiler needs to allocate storage according to a const int value. C++ standard doesn't support variable length array right now.
In C99, this syntax of variable length array is valid, but C++ standard says no. It is a very useful feature, leaving all the hairy memory allocating stuff to the compiler.
In GCC and Clang, this feature is supported as a compiler extension, so you won't get any warning and error. But MSVC compiler will put an error message that says cannot allocate an array of constant size 0, So it is compiler specific.
The compiler that supports this feature may have convert your code with new operator.
int a;
cin>>a;
float *b = new float[a];
This is valid in C++ standard.
Another thing is that though it is called variable-length array, it is not length-variable at all. Once it is defined, its length is a constant value which never change. You can't expand it or shrink it.
It is much better to use the vector container which is truly length variable, and with much more scalability and adaptivity.
See the post for more discussion on Why aren't variable-length arrays part of the C++ standard?
Related
I really need to do something like this in my code:
char str[var+1];
but i know you can only put a constant between []. So i'm just asking if there is any way of doing what i need.
It is only possible to declare a variable of compile time constant size in C++.
However, dynamic arrays can have a dynamic size. Simplest way to create a dynamic array is to use std::vector, or in case of character string you can use std::string. Example:
std::string str(var+1, '\0');
Question originaly included the C and C++ tag, this answer is for C
in C, var can be non-constant for VLA suporting standards (c99 and optional support in c11)
The following is valid in C (see : https://godbolt.org/z/kUockA)
int var=3;
char str[var+1];
However VLA are not defined in the C++ standard (see: https://stackoverflow.com/a/1887178/105104 ) and not recommended to use in C either.
Because VLA are usually allocated on the stack and if the value of var is not controlled the allocation of str can fail, and recovery of such failure can be difficult. Additionally they could encourage the creation of highly unsafe code (if one would want to make pointer arithmetic on stack allocated variable).
There was an initiative to make the linux kernel code VLA-free (see : https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kills-The-VLA ):
Using variable-length arrays can add some minor run-time overhead to the code due to needing to determine the size of the array at run-time.
VLAs within structures is not supported by the LLVM Clang compiler and thus an issue for those wanting to build the kernel outside of GCC, Clang only supports the C99-style VLAs.
Arguably most importantly is there can be security implications from VLAs around the kernel's stack usage.
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).
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".
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.
I want to define a 2D array statically. The size of the array is determined by a variable.
How do I do this? I do not want to dynamically define the array. I heard that there is a way to do this.
Answer is No You Cannot in C++.
Dimensions of the array must be known at compile time.
int my_array[6][7]; // okay
int my_array[H][7]; // ISO C++ forbids variable length array
int my_array[6][W]; // ISO C++ forbids variable length array
int my_array[H][W]; // ISO C++ forbids variable length array
Some compilers do support Variable Length Arrays(VLA) through their own extension but VLA are not defined in the C++ standard, hence using VLA will be non conforming to C++ standard.
VLA's were introduced in C99 C standard. C++ was branched out from C standard of C98. By the time C introduced VLA, C++ already had Vectors and had no need to support or encourage VLA. Hence, VLA was never formally accepted in the C++ Standard, some C++ compiler still support VLA through compiler extensions.
Since, you tagged your Q C as well as C++, to summarize the answer:
In C99 & versions after that : You Can
Versions before C99: You Can't
In C++(Any version): You can(through compiler extensions) but You should'nt
Here is the legendary C++ FAQ which explains everything about arrays.
I learned a lot from it. :)
If one of the dimensions of the array is variable, then the size must be variable, then it must be dynamically sized - or sized in such a way that the the array is statically sized larger than the largest value that the variable could be.
I dont think so you can statically define it! However you can use vector but underneath it too does dynamic allocation for you
By "variable", I assume you're talking about a non-constant value.
In C99, yes:
int size = ...;
int array[size][size];
In C++, you can't. The alternative is to use pointers and dynamic allocation (or better yet, vectors).
In C versions prior to C99, it's also impossible. Use malloc().
This depends where and when the variable is initialized. If its something done at compile time you can use templates to get it done: template </* args */> struct ConstExpr{enum{value = /* math goes here */};};, else its impossible without selfmodifying code(and I'm pretty sure this is gonna very dangerous, because you'll need to alter the PE so you can somehow get your allocated space change before its virtualized).