0

In the following code if I declare the variable-length array 'int array1[x]' before scanning the desired length of the array 'x', I receive ' segmentation fault (core dumped)' while execution. (compilation is error-free). I used strictly ANSI C99 standards by using option -std=c99 while compiling.

My question is Why can't I club all the declarations together?

// code to find a minimum value in a variable-length array
#include<stdio.h>

int minval(int [], int); 

int main(void)
{
    int x, i;

    int minivalue;

    printf("Enter the total number of array elements you wish to define?");
    scanf("%i",&x);

    int array1[x];          

    printf("Enter the elements now:");
    for (i = 0; i < x; i++)
        scanf("%i",&array1[i]);

    minivalue = minval(array1, x);

    printf("\nMinimum value in the array is = %i\n",minivalue);

    return 0;
}

int minval(int array2[], int x)     
{
    int i;
    int minivalue;

    minivalue = array2[0];

    for (i=0; i < x; i++){
        if (minivalue > array2[i])
            minivalue = array2[i];  
    }

    return (minivalue);
}
KawaiKx
  • 9,558
  • 19
  • 72
  • 111
  • That's not valid C. I'm actually surprised it even compiles. You'll need to use dynamic memory allocation (in other words `malloc`). – Corbin Apr 24 '12 at 08:44
  • it compiles and runs properly. I used -std=c99 option too for compiling. – KawaiKx Apr 24 '12 at 08:50
  • It's either a GCC extension then, or a special case in the standard (I suspect a GCC extension). – Corbin Apr 24 '12 at 08:51
  • @Corbin but why it is not valid. standard says a variable can be declared anywhere in the program as long as the declaration occurs before the variable is first used. – KawaiKx Apr 24 '12 at 09:01
  • Because you can't declare an array with a variable like that. `int a[x]` is not considered valid. That's because it depends on a dynamic allocation. That's because x's value is not known at compile time. If the value of x is known at compile time, it is valid. I suspect that what is happening when you place it after is that a GCC extension is automatically converting it to Emanuele Bezzi's answer. When it's placed before, GCC is doing the same, except `x1` is not initialized and therefore the malloc has the potential to go horribly wrong. – Corbin Apr 24 '12 at 09:04
  • @Corbin But I am using the option '-std=c99' which instructs the gcc to use strictly the ANSI C99 standards. And also the book I am learning C from ' Programming in C' by Stephen Kochan doesn't call it invalid. the book says ' so although this declaration appears out of place, its perfectly legitimate.' – KawaiKx Apr 24 '12 at 10:20
  • http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html It appears it is valid C99 (but *only* C99, not C90 or C++). I would assume that the problem is still what I said in the second part of my comment though. If the x variable hasn't been initialized yet, it will contain some random value, and thus an attempt might be made to allocate 3 elements, -5 elements or 139833234 elements. As you can see, that will obviously cause problems. Thus, x must be initialized before array declaration. – Corbin Apr 24 '12 at 10:26

3 Answers3

5

In the following code if I declare the variable-length array 'int array1[x]' before scanning the desired length of the array 'x', I receive ' segmentation fault (core dumped)' while execution.

You cannot declare a variable length array with an uninitialized value.

When you move the int array1[x] before the scanf() the x does not have a valid value.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • but x is actually initialised when the program is run. so how does it matter for the compiler if x is initialised or not while compilation? I am not able to understand why compiler behaves differently if nothing else except the location of the array declaration is changed? – KawaiKx Apr 25 '12 at 16:17
  • No, `x` is not initialized. To be initialized you'd have to have `int x = 42;`. With the plain `int x;` you're only *defining* `x`. – pmg Apr 25 '12 at 16:43
  • Now my question is how does it matter to compiler if an array is declared before or after the scanning statement? remember the variable, this array uses is already declared!.. – KawaiKx Apr 26 '12 at 06:17
  • declaration is not definition. A declaration (`int x;`) tells the compiler the name being declared is an object of a certain type; a definition (`int x = 42;`) tells the compiler the same as a declaration **and** the object value. In your problem code the object named `x` is declared, not initialized ... its value is garbage until it gets assigned a value (at the `scanf()` call). – pmg Apr 26 '12 at 08:41
0

Replace

int array1[x]; 

with

int* array1 = (int*) malloc (x * sizeof int);

so you allocate enough memory to have x elements contained in array1.

Do not forget to free the memory after, by adding

free(array1)

at the end of your program.

Emanuele Bezzi
  • 1,708
  • 14
  • 15
  • 3
    -1. This would not solve his problem. Variable length arrays are valid C99. What is currently happening when he moves the statement up is that `x` is uninitialised. The segfault is probably caused by the value being too big and the stack overflowing. If he moved the statement but used `malloc` as you suggest, it just hides the problem. In cases where `x` holds a value `>=` the allocation might succeed but you are still relying on undefined behaviour. – Mike Kwan Apr 25 '12 at 13:29
  • X is initialized only during runtime. isn't it? then how does shifting the array declaration below the scanning statement helps the code run? thats my question.. – KawaiKx Apr 28 '12 at 03:52
0

@Saurabh: try playing "computer" at runtime in the C99 standard. you come across the declaration int x. it has some large garbage value. then you read the array declartion with the large value - you try to allocate that - run out of stack memory - you seg fault. instead if you read a value for x first that is reasonable in size and then the array allocation, you are able to allocate the memory on the stack. regardless, this c99 feature is bad. use std::vector instead.

gupta
  • 9
  • 1