why can we do this in c?
int n;
scanf("%d",&n);
int a[n];
I thought array is located memory during load time but seems like the above example works during runtime.
Do I misunderstand any thing? can you guys help?
Thanks,
I am no expert in C, but this could be a variable-length array as added by C99 and supported by GCC, for example. GCC allocates the memory for such array on stack, so that it gets automatically freed when you return from the function.
Variable-length arrays are not found in C89, but are a new feature in C99.
I thought array is *al*located memory during load time but seems like the above example works during run-time.
Yes, ordinary arrays like <datatype> <Array_Name> [<size>] is allocated memory during load time it is there in C89 and also existed in C99.
But in the code snippet int a[n]; is a Variable Length Array or VLA for short.VLA's in C99 are defined just like any other array, except that the length doesn’t need to be a compile-time constant.
A decent article on the need of VLAs can be found here :http://www.ddj.com/cpp/184401444 :)
Given how your code is written (specifically, that you have a statement), this must be code within a function.
While I'm not sure if this is strictly required in the spec, within a function, all auto (i.e. function level, not static) arrays are put on the stack. So regardless of whether you have a regular or VL array, the memory is allocated at runtime.
The memory for non-auto arrays is not handled at runtime so do no support VLA. If you try to compile the following code:
extern int size;
char buff1[size];
void doit(int x)
{
static int buff2[x];
int buff3[x];
}
On the compiler I tested this on (gcc 4.2.1), I got following errors:
moo.c:2: error: variably modified ‘buff1’ at file scope
moo.c: In function ‘doit’:
moo.c:6: error: storage size of ‘buff2’ isn’t constant
Related
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.
I was writing the following code
#include<stdio.h>
void fun(int n) {
int a[n] = {0};
}
void main() {
int a[4] = {0};
int i = 0;
fun(3);
}
and got this error
test.c: In function 'fun':
test.c:5:5: error: variable-sized object may not be initialized
while if I change the function fun to:-
void fun(int n) {
int a[n], i = 0;
for(i = 0; i < n; i++) {
a[i] = 0;
}
}
it works fine.
I know that the error is occuring because it's not allowed in the compiler's specification but what i want to know is why is it not possible to be implemented?
Is it due to some compile time or run time evaluation issue?
I have seen the answer of other question but i need a more elaborated answer.
Variable Length Array cannot be initialized like this
int a[n]={0};
From C Standards#6.7.9p3 Initialization [emphasis added]
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
Using loop is one way to initialize the variable length array's. You can also use memset like this:
memset(a, 0, sizeof a);
Additional:
The C99 compiler should support the Variable Length Array's but they were made optional in C11 compiler.
An easy way is to send the size of array along with other parameters
Remember that you should send size before an array with that size
void fun(int n,int a[n]){
}
Although you have other alternatives like sizeof()
As an addition to H.S. answer:
From C Standards#6.7.9p3 Initialization [emphasis added]
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
This is probably because Initializers have to be constant expressions. Constant expression have a definite value at compile time.
A {0} is an incomplete Initializer and the compiler would fill up the remaining values with 0.
If you have a VLA the compiler does not know the length of the Array and thus can not generate the initializer for it.
This depends on your compiler actually.
In old C You couldn't have variable size arrays. In function fun you use a as an array with variable size n. This is not allowed in old C. However, C99 and C11 standards support variable size arrays, so perhaps you have an old compiler. (DevC?) If you want to use some type of variable arrays in older C compilers, you have to use malloc and free.
Perhaps you wanted to write this code in C++? C++ doesn't support variable size arrays also, but the gcc compiler can run this code.
Check this out:
Why aren't variable-length arrays part of the C++ standard?
If you are using DevC, I think that if you change your file from test.c to test.cpp this code will work.
I am trying to create an array according to the size that the user inputs but it does not seem to be working for c programming. The following are my codes:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int x, y;
scanf("%d", &x);
scanf("%d", &y);
double arr[x][y];
}
The compiler keeps returning an error of" Error: Expression must have a constant value. at the line double ... could anyone help point out the error?
You have two choices:
Either use a decent C compiler that supports C99 (or later) and variable-length arrays (I'd go with this approach, personally);
or if that is not possible, or the resulting array would be too large to fit in a block-scope variable (causing, for example, a stack overflow), you can use malloc(); however, you won't be able to create a true two-dimensional array using that approach, only a pointer-to-pointer, which may or may not be what you are looking for.
The code can work in C99 mode or when the compiler supports VLA(variable length arrays) as an extension (e.g, GCC supports VLA as GNU extesnion).
In C89, you have to use pointers with dynamic memory to simulate.
Older C standards don't provide support for arrays that do not have compile-time sizes:
int array[42];
char text[] = "Hello World";
int numbers = { 1, 2, 3, 4 };
(in the case of the latter two examples, the size is derived from the data)
You either need a newer compiler, to specify the -std=c99 if you are using GCC, or you need to allocate memory for the array yourself.
You're using a C89 (Visual Studio? Though that would give you an error on the declaration of arr next) or a C++ compiler. VLA's (Variable Length Arrays) are a C99 feature.
You need to allocate the memory in run-time . The compiler doesn't allow the declaration of arrays becuase it does not know the size of the array before hand . You need to use malloc() to allocate memory
int num = atoi(argv[1]);
unsigned long times[num];
I have this code and I assumed it won't compile because I am trying to allocate the array using a value from a command line argument, which compiler doesn't know at the compile time.
But I compiled this code and it worked.
Can someone explain what is going on here??
Am I misunderstanding the basic concept of static allocation??
C99 allows to allocate an array with a var. This is called variable length arrays aka VLA
I don't have the C99 in my hand, the section is 6.7.5.2 in C99, and the following links are from the internet.
vla - wikipedia
c99 - wikipedia
be aware that vla is not supported in c++, more information here
I need to create a shared vector, with the same size as the block.
__global__ func()
{
const int size = blockDim.x;
__shared__ float* Vec[size];
..
}
I get this error
error : expression must have a constant value
I cannot understand where is the problem, sinceblockDim.x is "constant" for each block threads??
Here's how you do it
_shared_ float Vec[size];
remove the star (*)
As far as I know, CUDA does not support variable length arrays (which is what you're trying to do here, regardless of the presence of the keyword const).
If you look at section B.16 of the CUDA C Programming Guide, there's some text on how to specify a size for an extern declared shared array. Although it's a bit more complicated, this is the syntax on how to specify execution-time sized shared arrays. The way you're doing it won't work.
You have to have a compiler that supports C99 to use variable-length arrays. It would seem your compiler doesn't support VLAs, so you have to have an integer constant expression for your array size.