This question already has answers here:
Variable Sized Arrays vs calloc in C
(5 answers)
Closed 7 years ago.
I was amazed to see that this code is working. I couldn't figure out why
#include<stdio.h>
int main(){
int row,col,i,j;
scanf("%d %d",&row,&col);
int a[row][col];
for(i=0;i<row;i++)
for(j=0;j<col;j++)
scanf("%d",&a[i][j]);
for(i=0;i<row;i++){
for(j=0;j<col;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}
Since C is a compiled language then How it is allocating memory for the array a[row][col] ? Since at the time of compilation the value of row and column are not known, then how it is able to make machine code and set the address space for the program? Why this is working as an interpreter language would have worked, If this is a way to create a dynamic array then why are we taught to use malloc for creating dynamic array in C.
Variable-length arrays have been a standard feature of C since C99.
How it is allocating memory for the array a[row][col]
Once the value of row and col is known, there is no problem for the compiled code to make this allocation in the automatic storage area (commonly referred to as "the stack").
how it is able to make machine code and set the address space for the program?
The compiler squirrels away the values of row and col for internal use by machine code that it generates. Instructions that reference a[i][j] look up the sizes, do the math, add the offset, and get the address, as if row and col were known at compile time.
The feature does change a few other things - for example, sizeof is no longer a purely compile-time operation, because the size of VLAs need to be computed at run-time.
why are we taught to use malloc for creating dynamic array in C.
malloc gives you more flexibility than a VLA. For example, you can return a malloc-created array from your function, while VLA gets automatically deallocated as soon as the function finishes. In addition, malloc is less likely to run your program out of memory, because dynamic storage area is more generously sized than the automatic one.
For example, if you try to enter 2000 2000 for your program, it is likely going to crash. Yet it would have no problem allocating the same amount of memory with malloc:
int (*a)[col] = malloc(row*col*sizeof(int));
That's feature of C99. The reason to use malloc anyway is that it allocates space not on the stack, but the heap - and the heap is where the 'heavy' data should be stored, as the stack space is severely limited. More than that; failure to do a stack allocation typically crashes the program - while allocating with malloc returns a NULL pointer, which allows you to proceed in elegant fashion.
Related
This question already has answers here:
Do I really need malloc?
(2 answers)
Closed 2 years ago.
As far as I know, the C compiler (I am using GCC 6) will scan the code in order to:
Finding syntax issues;
Allocating memory to the program (Static allocation concept);
So why does this code work?
int main(){
int integers_amount; // each int has 4 bytes
printf("How many intergers do you wanna store? \n");
scanf("%d", &integers_amount);
int array[integers_amount];
printf("Size of array: %d\n", sizeof(array)); // Should be 4 times integer_amount
for(int i = 0; i < integers_amount; i++){
int integer;
printf("Type the integer: \n");
scanf("%d", &integer);
array[i] = integer;
}
for(int j = 0; j < integers_amount; j++){
printf("Integer typed: %d \n", array[j]);
}
return 0;
}
My point is:
How does the C compiler infer the size of the array during compilation time?
I mean, it was declared but its value has not been informed just yet (Compilation time). I really believed that the compiler allocated the needed amount of memory (in bytes) at compilation time - That is the concept of static allocation matter of fact.
From what I could see, the allocation for the variable 'array' is done during runtime, only after the user has informed the 'size' of the array. Is that correct?
I thought that dynamic allocation was used to use the needed memory only (let's say that I declare an integer array of size 10 because I don't know how many values the user will need to hold there, but I ended up only using 7, so I have a waste of 12 bytes).
If during runtime I have those bytes informed I can allocate only the memory needed. However, it doesn't seem to be the case because from the code we can see that the array is only allocated during runtime.
Can I have some help understanding that?
Thanks in advance.
How does the C compiler infer the size of the array during compilation time?
It's what's called a variable length array or for short a VLA, the size is determined at runtime but it's a one off, you cannot resize anymore. Some compilers even warn you about the usage of such arrays, as they are stored in the stack, which has a very limited size, it can potencially cause a stackoverflow.
From what I could see, the allocation for the variable 'array' is done during runtime, only after the user has informed the 'size' of the array. Is that correct?
Yes, that is correct. That's why these can be dangerous, the compiler won't know what is the size of the array at compile time, so if it's too large there is nothing it can do to avoid problems. For that reason C++ forbids VLA's.
let's say that I declare an integer array of size 10 because I don't know how many values the user will need to hold there, but I ended up only using 7, so I have a waste of 12 bytes
Contrary to fixed size arrays, a variable length array size can be determined at runtime, but when its size is defined you can no longer change it, for that you have dynamic memory allocation (discussed ahead) if you are really set on having the exact size needed, and not one byte more.
Anyway, if you are expecting an outside value to set the size of the array, odds are that it is the size you need, if not, well there is nothing you can do, aside from the mentioned dynamic memory allocation, in any case it's better to have a little more wasted space than too little space.
Can I have some help understanding that?
There are three concepts I find relevant to the discussion:
Fixed size arrays, i.e. int array[10]:
Their size defined at compile time, they cannot be resized and are useful if you already know the size they should have.
Variable length arrays, i.e. int array[size], size being a non constant variable:
Their size is defined at runtime, but can only be set once, they are useful if the size of the array is dependant on external values, e.g. a user input or some value retrived from a file.
Dynamically allocated arrays: i.e. int *array = malloc(sizeof *arr * size), size may or may not be a constant:
These are used when your array will need to be resized, or if it's too large to store in the stack, which has limited size. You can change its size at any point in your code using realloc, which may simply resize the array or, as #Peter reminded, may simply allocate a new array and copy the contents of the old one over.
Variables defined inside functions, like array in your snippet (main is a function like any other!), have "automatic" storage duration; typically, this translates to them being on the "stack", a universal concept for a first in/last out storage which gets built and unbuilt as functions are entered and exited.
The "stack" simply is an address which keeps track of the current edge of unused storage available for local variables of a function. The compiler emits code for moving it "forward" when a function is entered in order to accommodate the memory needs of local variables and to move it "backward" when the program flow leaves the function (the double quotes are there because the stack may as well grow towards smaller addresses).
Typically these stack adjustments upon entering into and returning from functions are computed at compile time; after all, the local variables are all visible in the program code. But principally, nothing keeps a program from changing the stack pointer "on the fly". Very early on, Unixes made use of this and provided a function which dynamically allocates space on the stack, called alloca(). The FreeBSD man page says: "The alloca() function appeared in Version 32V AT&T UNIX"ยด(which was released in 1979).
alloca behaves very much like alloc except that the storage is lost when the current function returns, and that it underlies the usual stack size restrictions.
So the first part of the answer is that your array does not have static storage duration. The memory where local variables will reside is not known at compile time (for example, a function with local variables in it may or may not be called at all, depending on run-time user input!). If it were, your astonishment would be entirely justified.
The second part of the answer is that array is a variable length array, a fairly new feature of the C programming language which was only added in 1999. It declares an object on the stack whose size is not known until run time (leading to the anti-paradigmatic consequence that sizeof(array) is not a compile time constant!).
One could argue that variable length arrays are only syntactic sugar around an alloca call; but alloca is, although widely available, not part of any standard.
What is the difference between defining an array of a length that is definied before runtime (depends on command line arguments) with array[size] and using malloc()? array[i] leads to the data put on the stack, malloc() uses the heap[see this stackoverflow]
So with large Data I can run into stackoverflows, but on a new machine a total of 30 chars and ints should not be problematic (Stack is around 1MB on windows according to this).
So I am probably missing something obvious.
As far as I understand, when defined in main(),the two should be the same:
Example 1
int size; // depends on some logic
char array[size];
Example 2
int size; // depends on some logic
array= (char *)malloc(size * sizeof(char));
free(array); // later after use
But when I use the array inside of functions and hand it over as a pointer (func(char* array)) or as an array (funct(char array[])), sometimes the gdb-debugger let's me know that the function gets handed corrupted data in #1 , using malloc() fixed the issue.
Is array[i], not okay to use when it is not determined at compile time? Is it some scoping issue? This answer has a comment suggesting such a thing, but I don't quite understand if that applies here.
I am using C99.
The main difference is that arrays declared with a fixed size are stack allocated (and references to it or its elements are valid only within its scope) while mallocd arrays are heap allocated.
Stack allocation means that variables are stored directly to the memory. Access to this memory is usually very fast as and it's allocation is done during compilation.
On the other hand, variables allocated on the heap have their memory allocated at runtime and - while accessing this memory is slower - your only limit is the size of virtual memory.
Have a look here:
https://gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html
This question already has answers here:
What's the difference between a VLA and dynamic memory allocation via malloc?
(4 answers)
Closed 6 years ago.
In the following code I'm providing size of array at run time.
#include <stdio.h>
int main()
{
int i;
scanf("%d",&i);
int a[i];
}
Please tell me the difference between the code above and code using malloc().
I know that array store is on the stack and dynamic memory (malloc, calloc etc) is on the heap.
So is my code functioning similar to malloc? If not, please explain.
Apart from your code uses VLA which:
did not exist before C99
were introduced as a new feature in C99
are now an optional feature since C11
The difference is that automatic arrays (VLA or static size ones) are automatically release when they go out of scope, so you cannot return them from a function, while dynamically allocated ones persist until they are explicitely freed - which shall happen before you lose a pointer to them if you do not want a memory leak.
The Above statement works in C99, but there are limitations of using this approach:
int a[i] is variable length array not the memory dynamically
allocated, hence it will store on STACK instead of HEAP "which it does
in case of malloc" hence there will be situation when somebody entered
MAX_INT and your STACK memory limit is very less(Ex : Embedded
Systems) then Stack Corruption might occur.
How compiler determine the size of below array at compile time?
int n;
scanf("%d",&n);
int a[n];
How it is different from dynamic allocation(other than memory is allocated in heap for dynamic array).
If possible please, explain this in terms of activation stack memory image how this array is allocated memory.
The array's size isn't determined at compile time; it's determined at run time. At the time that the array is allocated, n has a known value. In typical implementations where automatic variables are allocated on the program stack, the stack pointer will be adjusted to make room for that many ints. It becomes parts of the stack frame and will be automatically reclaimed when it goes out of scope.
This code was not valid in C90; C90 required that all variables be declared at the beginning of the block, so mixing declarations and code like this was not permitted. Variable-length arrays and mixed code and declarations were introduced in C99.
In C the proper name for the allocation type is automatic. In computing jargon the term stack is sometimes used synonymously.
The storage of a is valid from the point of definition int a[n]; up until the end of the enclosing scope (i.e. the end of the current function, or earlier).
It is just the same as int a[50]; , except that a different number of ints than 50 may be allocated.
A drawback of using automatic arrays (with or without runtime sizes) is that there is no portable way to protect against stack overflow. (Actually, stack overflow from automatic variables is something the C standard does not address at all, but it is a real problem in practice).
If you were to use dynamic allocation (i.e. malloc and friends) then it will let you know if there is insufficient memory by returning NULL, whereas stack overflows are nasty.
This question already has answers here:
What's the difference between a VLA and dynamic memory allocation via malloc?
(4 answers)
Closed 6 years ago.
There are two ways to allocate memory to an array, of which the size is unknown at the beginning. The most common way is using malloc like this
int * array;
... // when we know the size
array = malloc(size*sizeof(int));
But it's valid too in C99 to define the array after we know the size.
... // when we know the size
int array[size];
Are they absolutely the same?
No they're not absolutely the same. While both let you store the same number and type of objects, keep in mind that:
You can free() a malloced array, but you can't free() a variable length array (although it goes out of scope and ceases to exist once the enclosing block is left). In technical jargon, they have different storage duration: allocated for malloc versus automatic for variable length arrays.
Although C has no concept of a stack, many implementation allocate a variable length array from the stack, while malloc allocates from the heap. This is an issue on stack-limited systems, e.g. many embedded operating systems, where the stack size is on the order of kB, while the heap is much larger.
It is also easier to test for a failed allocation with malloc than with a variable length array.
malloced memory can be changed in size with realloc(), while VLAs can't (more precisely only by executing the block again with a different array dimension--which loses the previous contents).
A hosted C89 implementation only supports malloc().
A hosted C11 implementation may not support variable length arrays (it then must define __STDC_NO_VLA__ as the integer 1 according to C11 6.10.8.3).
Everything else I have missed :-)