statically define an array based on a variable value C/C++ - c++

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

Related

Is there any way of declaring a variable of another variable's size in C++?

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.

Can I use a C Variable Length Array in C++03 and C++11?

C has a really cool feature called variable length arrays. Its available in C90 and above, and it allows deferring the size of the array until runtime. See GCC's manual 6.19 Arrays of Variable Length.
I'm working in C++. At std=c++11, I'm catching a compile failure due to the use of alloca under Cygwin. I want to switch to variable length arrays, if possible. I also want to try and avoid std::vector and std::array because I want to stay out of the memory manager. I believe every little bit helps, so I'm happy to take these opportunities (that some folks consider peepholes).
Can I use a variable length array in C++03 and C++11?
VLAs are not in standard C++03 or C++11, so you'll better avoid them if you want to write strictly standard conforming code (and use e.g. std::vector, which generally use heap for its data - but you might use your own allocator...).
However, several C++ compilers (recent GCC & Clang) are accepting VLAs as an extension.
It is the same for flexible array members; they are not standard in C++ (only in C) but some compilers accept them.
dynarray-s did not get into the C++11 standard...
Not if you want code that is standard C++.
No C++ standard supports VLAs, but some C++ compilers do as a vendor-specific extension.
You can achieve a similar effect in C++ using the standard vector. Note that, unlike VLAs which can only be sized when created, a standard vector can be resized as needed (subject to performing appropriate operations on it).

Initializing an array

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?

define the length of an array with a variable in c++/c

I am reading a book saying that in C++ you can't do this:
int array_size = 3;
int array[array_size];
Then I tried it with gcc,but it didn't complain at all(exception warned about unused array).
Also I read about this question.The 4th answer says that you can use something like this:char someCondition[ condition ];To me the condition would only be known until runtime,so the whole thing seems really confounding to me.Can anyone help explain this?
Thanks,G
If You are using a C++ compiler it works because most of the C++ compilers provide a compiler extension that supports Variable Length arguments(VLA).
If You are using a C compiler it works because the standard allows it.
In C++, VLA are not allowed by the C++ Standard, so any usage of it through compiler extensions will make your code non portable.
C++ provides std::vector or std::array(C++11) which satisfy all the requirements using variable length array or c-style arrays resp and you should use them.
Note that,since C99 standard, VLA's are allowed in C.

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