Trouble with VLA's in C - c

I'm running Xcode 7.1 on Mac OS X 10.11. I'm trying to declare a VLA array in C but I can't do it.
The second I use a variable in the array declaration, it's moot. The array doesn't get created. I've dug around in the compiler settings, tried installing GCC manually, I can't figure this out. Can anyone spot the issue? From what I understand VLA's became standard since C99 and from what I can tell my Xcode is running on C11. What is the deal here? Code and settings images included.
void printTriangle (int height, char rowPatterns[][height]) {
int rowSize = 2 * height - 1;
char rowString[rowSize]; //string to store in pattern's array
int characterCount = rowSize; //number of character printed per row of triangle
int asteriskCount = 1; //number of asterisks printed in each row
int spaces = (characterCount - asteriskCount) / 2; //how many spaces need to be printed in this current row
int rowCount;
// rest of the code...
}

A VLA, like any other local variable, is probably not even allocated before the moment you use it for the first time. Modern compilers do not necessarily allocate local variables at the point of declaration, most often they don't. Therefore, attempting to view the contents of a VLA in a debugger just after the point of declaration is not meaningful.

Related

How do I allocate the size of an array dynamically?

include <stdio.h>
int main() {
int num = 10;
int arr[num];
for(int i = 0; i < num; i++){
arr[num] = i+1;
}
}
Some colleague of mine says that this code is not correct and that it is illegal. However, when I am running it, it is working without any errors. And he does not know how to explain why it is working and why I should not code like this. Can you please help me. I am a beginner and I want to learn C.
If you want to dynamically allocate an array of length n ints, you'll need to use either malloc or calloc. Calloc is preferred for array allocation because it has a built in multiplication overflow check.
int num = 10;
int *arr = calloc(num, sizeof(*arr));
//Do whatever you need to do with arr
free(arr);
arr = NULL;
Whenever you allocate memory with malloc or calloc, always remember to free it afterwards, then set the pointer to NULL in order to prevent any accidental, future references, as well as to prevent a double free.
While not necessarily illegal, this code won't do what you intend. When you declare an array, you declare the number of items you want to store, in this instance num. So when you declare num = 10 and arr[num] you get an array that can hold 10 integers. C arrays are indexed from 0, so the indices are 0-9, not 1-10. This is probably what they mean by illegal. Since you are writing to arr[num] or arr[10], you are attempting to use memory beyond the memory allocated for the array.
Additionally, if I understand the intent of the program correctly, you want to fill in the array with the numbers 1-10. To do this, you'd need to access each index individually. You're almost there, the only problem being arr[num] = i + 1;. As mentioned before, it is beyond the end of the array. However, you should probably be using i as your index, so arr[i], because this will access each index, 0-9.
Are you learning C or C++?
Your colleague meant that in that code of yours you are doing something different from what you wanted. It's working because of some additional factors. Because C/C++ standards are evolving and so do compilers as well. Let me show you.
Static array
When you a beginner, it's generally advised to stick to the concept that "a typed array of the compilation-given size" is int arr[N], where N is a constant. You allocate it on the stack and you don't manage it's memory.
In C++11 you can use a constexpr (constant expression), but is still not an arbitrary variable.
In C++14 you can use a "simple expression" for size, but you shouldn't try a lot of it before getting the array concept beforehand. Also, GCC compiler provides an extension to support variable sized arrays, it could be an explanation of "why the code is working at all".
Notice: variable sized arrays are not the same as dynamic arrays. They are not that static arrays from the first chapter of a C/C++ guide book as well.
There also exists a modern approach – std::array<int, 10> but once again, don't start with it.
Dynamic array
When you need to create an array in runtime everything changes. First of all, you allocate it on the heap and either you mange it's memory yourself (if you do not, you get a memory leak, a Pure C way) or use special C++ classes like std::vector. Once again, vectors should be used after getting to know Pure C arrays.
Your colleague must have been meaning something like that:
int* arr = new int[some_variable]; // this is dynamic array allocation
delete[] arr; // in modern C/C++ you can write "delete arr;" as well
So, your compiler made it work in this exact case, but you definitely should not rely on the approach you've tried. It's not an array allocation at all.
TL;DR:
In C++ variable length arrays are not legal
g++ compiler allows variable length arrays, because C99 allows them
Remember that C and C++ are two different languages
The piece of code from the question seems to be not doing what you'd wanted it to do
As others mentioned, it should be arr[i] = i + 1 instead, you are assigning to the same array item all the time otherwise

Array initialization at runtime

code link
#include <stdio.h>
int main(void) {
// your code goes here
int a = 2;
int b = 3;
int c;
c = a + b;
int arr[c];
arr[5] = 0;
printf("%d",arr[5]);
return 0;
}
Output is 0
How is it that at runtime it is taking the array number ? Is it a new feature ?
This is a variable length array. They were introduced in the 1999 revision of the C standard.
Sadly support for them came in slowly, so much that the 2011 revision made them an optional feature (but they are still standardized) 1.
Despite looking cool, they have a major caveat. They can cause you to overflow the call stack if the size is "too big". As such, care needs to be taken when using them.
1 Some compiler vendors were resistant, so it was made optional to appease them. Microsoft is an entire case study of this.
This feature (Variable length array) has been introduced in C99. But currently this still is a compiler-dependent behavior. Some compiler(like gcc) supports it. Some(like msvc) doesn't.
BTW, arr[5] in your code, is out of range. Last element should be arr[4].
don't be confused in (static/fixed memory allocation) & (dynamic memory allocation) concepts :)
Let me clear your concept bro.
Relevant to following question,
C supports two type of array.
1.Static Array - are allocated memory at "COMPILE TIME".
2.Dynamic Array - are allocated memory at "RUN TIME".
Ques. how to determine if an Array is static or dynamic?
Ans.
Array declaration syntax:-
int array_Name[size]; //size defines the size of block of memory for an array;
So, coming to the point-->
Point 1. if size is given at compile time to array, it's a "Static Memory Allocation". It is also called "fixed size memory allocation" because size is never changed. It's the LIMITATION of ARRAY in C.
ex.
int arr[10]; //10 is size of arr which is staticly defined
int brr[] = {1000, 2, 37, 755, 3}; //size is equal to the no. of values initilizes with.
point 2. If size is given at compile time to array, it's a Dynamic Memory Allocation.
It is achieved by malloc() function defined in stdlib.h .
Now, its's the clarification of your code :-
#include <stdio.h>
int main(void) {
// your code goes here
int a = 2;
int b = 3;
int c;
c = a + b; //c is calculated at run time
int arr[c]; //Compilor awaiting for the value of c which is given at run time but,
arr[5] = 0; //here arr is allocated the size of 5 at static(compile) time which is never be change further whether it is compile time in next statements or run time.
printf("%d",arr[5]);
return 0;
}
So, array(of size 5) holds value 0 at arr[5].
and ,other array indexes still show Garbage Values.
Hoping, you'll be satisfy with this solution to your problem :)

What is the correct way to allocate memory for an array depending on a command line parameter?

When writing a program in which I ask the user to enter number N, which I have to use to allocate the memory for an int array, what is the correct way to handle this:
First approach:
int main() {
int array[],n;
scanf("%d\n",&n);
array = malloc(n * sizeof(int));
}
or the second approach:
int main() {
int n;
scanf("%d\n",&n);
int array[n];
}
Either one will work (though the first case needs to be changed from int array[] to int *array); the difference depends on where the array is stored.
In the first case, the array will be stored in the heap, while in the second case, it'll (most likely) be stored on the stack. When it's stored on the stack, the maximum size of the array will be much more limited based on the limit of the stack size. If it's stored in the heap, however, it can be much larger.
Your second approach is called a variable length array (VLA), and is supported only as of c99. This means that if you intend your code to be compatible with older compilers (or to be read and understood by older people..), you may have to fall back to the first option which is more standard. Note that dynamically allocating data requires proper maintenance, the most important part of that being - freeing it when you're done (which you don't do in your program)
Assuming you meant to use int *array; instead of int array[];(The first one wouldn't compile).
Always use the first approach unless you know the array size is going to be very small and you have the intimate knowledge of the platforms your will be running on. Naturally, the question arises how small is small enough?
The main problem with second approach is that there's no portable way to verify whether the VLA (Varible Length Array) allocation succeeded. The advantage is that you don't have to manage the memory but that's hardly an "advantage" considering the risk of undefined behaviour in case memory allocation fails.
It was introduced in C99 and been made optional in C11. That suggests the committee found it not-so-useful. Also, C11 compilers may not support it and you have to perform additional check whether your compiler supports it or not by checking if __STDC_NO_VLA__ has been defined.
Automatic storage allocation for an array as small int my_arr[10]; could fail. This is an extreme and unrealistic example in modern operating systems, but possible in theory. So I suggest to avoid VLAs in any serious projects.
You did say you wanted a COMMAND LINE parameter:
int main (int argc, char **argv)
{
int *array ;
int count ;
if (argc < 2)
return 1 ;
count = atoi (argv[1]) ;
array = malloc (sizeof(int)*count) ;
. . . . .
free (array) ;
return 0 ;
}

C global unsized array?

We had a school project, any information system using C. To keep a dynamic-sized list of student records, I went for a linked list data structure. This morning my friend let me see his system. I was surprised with his list of records:
#include <stdio.h>
/* and the rest of the includes */
/* global unsized array */
int array[];
int main()
{
int n;
for (n=0; n < 5; n ++) {
array[n] = n;
}
for (n=0; n < 5; n ++) {
printf("array[%d] = %d\n", n, array[n]);
}
return 0;
}
As with the code, he declared an unsized array that is global (in the bss segment) to the whole program. He was able to add new entries to the array by overwriting subsequent blocks of memory with a value other than zero so that he can traverse the array thusly:
for (n=0; array[n]; n++) {
/* do something */
}
He used (I also tested it with) Turbo C v1. I tried it in linux and it also works.
As I never encountered this technique before, I am presuming there is a problem with it. So, yeah, I wanna know why this is a bad idea and why prefer this over a linked list.
int array[];
Is technically known as an array with incomplete type. Simply put it is equivalent to:
int array[1];
This is not good simply because:
It produces an Undefined behavior. The primary use of array with incomplete type is in Struct Hack. Note that incomplete array types where standardized in C99 and they are illegal before.
This is Undefined behaviour. You are writing to unallocated memory (beyond the array). In order to compile this, the compiler is allocating at least one element, and you're then writing beyond that. Try a much bigger range of numbers. For example, if I run your code on Linux it works, but if I change the loop to 50,000, it crashes.
EDIT The code may work for small values of n but for larger values it will fail. To demonstrate this I've written your code and tested it for n = 1000.
Here is the link for CODEPAD, and you can see that for n = 1000, a segmentation fault happens.
Whereas with the same code with the same compiler, it is working for n = 10, see this link CODEPAD. So this is called Undefined behavior.
If you use linked lists you can check whether the memory is allocated properly or not.
int *ptr;
ptr = (int *)malloc(sizeof(int))
if(ptr==NULL)
{
printf("No Memory!!!");
}
But with your code the program simply crashes if tested with an array having a large bound.

ANSI C Program: How to initialize numeric array when length is determined when program runs?

Newbie to C. I'm writing an ANSI C program (on Linux using gcc 4.4.6) and need to know how to initilize a numeric array, such as int or double, where the length of the array is determined when the program is run?
Does ANSI C allow one to declare variable, execute some code (wherein the length is determined), then declare additional variables (e.g. the arrays in question)?
If not, how is this done in practice? Note the program compiles using gcc -ansi ... switch.
You need to allocate the memory for the array and free it after you are done.
See malloc and free and get one of the beginner books listed here. Attempting to write C without a solid foundation ends in blood, tears and segfaults. Think of the children. Don't do it.
Example to get you started with shooting yourself in the foot:
int* intarray = NULL;
intarray = (int*)malloc(sizeof(int) * 23); // allocate space for 23 intS
To make a dynamic array, you'd instead use a pointer; the usage is pretty much the same, but you need to free() the memory once you're done with it;
int staticArray[10];
int *dynamicArray;
// calculate length of the dynamic array here
int length = 3*4;
dynamicArray = (int*)malloc(length * sizeof(int));
staticArray[4] = 7;
dynamicArray[8] = 5;
free(dynamicArray);
I would recommend alloca over malloc if you would like the data allocated on the stack (and if it's available), but malloc will work in most situations.
Note that GCC allows for flexible length arrays, even when compiled with -ansi, so you can just do this:
int size = 0;
printf("please enter array size: ");
scanf("%i", &size);
data_type data[size];
However, if you must have it dynamically allocated, you can simply replace the last line with this:
data_type *data = alloca(size * sizeof(*data));
Does ANSI C allow one to declare variable, execute some code (wherein the length is determined), then declare additional variables (e.g. the arrays in question)?
As of the 1999 standard, you can mingle declarations and code within a block; prior to that, all declarations within a block had to precede code. To compile for C99, use -std=c99 instead of -ansi (which is synonymous with -std=c89). So the following would be legal in C99:
int main(void)
{
int size;
// get the size somehow
int *array = malloc(sizeof *array * size);
...
// don't forget to clean up when you're done
free(array);
}
If you must compile with the -ansi flag (meaning you must conform to the C89 standard), you'd have to structure your code like so:
int main(void)
{
int size;
int *array;
// get size somehow
array = malloc(sizeof *array * size);
...
free(array);
}
Note that C99 also supports variable length arrays, which allow you to specify the size of an array at run time:
int main(void)
{
int size;
// get size as before
int array[size];
...
}
VLAs are somewhat limited compared to regular arrays (they can't be members of struct or union types, and they can't appear outside of a function), and must be used with care; if you need to allocate a lot of space, use malloc instead. Their implementation turned out to be complicated enough that the recently-approved 2011 standard gives implementations the option to not support them.

Resources