1
#include<stdio.h>
#include<stdlib.h>
#define max 10
void init_graph(int arr[max][max],int v);
void create_graph(int arr[max][max],int v);
void print_graph(int  arr[max][max],int v);
int main()
{
    int v,n;
    printf("Enter the number of vertices :");
    scanf("%d",&v);
    int arr[v][v];
    init_graph(arr,v);
    printf("v=%d after init\n",v);
    create_graph(arr,v);
    print_graph(arr,v);
    return 0;
}
void create_graph(int arr[max][max],int v)
{
    printf("v=%d \n",v);
    int e;
    printf("Enter the number of edges :");
    scanf("%d",&e);
    int i,src=0,dest=0;
    for(i=0;i<e;i++)
    {
        printf("Enter Edge :%d",i+1);
        scanf("%d %d",&src,&dest);
        if(src<=-1 || src>=v)
        {
            printf("Invalid source vertex \n");
            i--;
            continue;
        }
        if(dest<=-1 || dest >=v)
        {
            printf("Invalid dest vertex \n");
            i--;
            continue;
        }
        //*(*(arr+src)+dest)=1;
        //*(*(arr+dest)+src)=1;
        arr[src][dest]=1;
        arr[dest][src]=1;
    }

}

void init_graph(int arr[max][max],int v)
{
    int i,j;
    for(i=0;i<v;i++)
    {
        for(j=0;j<v;j++)
        {
            //*(*(arr+i)+j)=0;
            arr[i][j]=0;
        }
    }
    printf("V=%d init_graph\n",v);
}

void print_graph(int arr[max][max],int v)
{
    int i,j;
    for(i=0;i<v;i++)
    {
        for(j=0;j<v;j++)
        {
            //printf("%d ",*(*(arr+i)+j));
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
}

When I compiled the above program in Dev-c++ and in gcc 4.8.2 I'm getting different output. Here I'm trying to represent a graph using adjacency matrix representation.

when v is passed as parameter to the init_graph(arr,v)(in the above program), even though I'm not returning any value from the function, the value of v is becoming zero after after the function has been called.

It is working properly in Dev-c++ but I'm getting the wrong answer when compiled in gcc.4.8.2.

enter image description here

Screenshot of the output in Dev-c++

here v is not becoming 0

enter image description here

Screenshot of the output in gcc 4.8.2

and here v is becoming 0.

JS1
  • 4,745
  • 1
  • 14
  • 19
prabhudas
  • 88
  • 10

3 Answers3

2

Due to the way "array" function parameters are "adjusted" to pointers in C, the create_graph function really accepts a pointer to an array of length max. It is equivalent to this:

void create_graph(int (*arr)[max], int v)

That means that when you each iteration over arr[i] in the loop takes a step of size 10 ints, to the next length 10 array. But you are passing (after array decay) a pointer to an array of length v. If v is not the same as max, that is already undefined behaviour (UB). In your case, this takes you out of bounds, (that would cause UB by itself in an otherwise well defined program.)

You can only call the function with a pointer to array of length max or with an array of arrays whose inner array length is max (the latter will decay to pointer to array.)

Note that the type of platform dependent behaviour you saw is often a sign thet there is UB in the code.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Thanks, I think this is a reponse we can all work with. To clarify that this is in fact the correct answer to the original question: *undefined behavior* basically means you can get any answer out there - but often means you're looking at implementation details or memory that's specific to the platform / compiler (and therefore get the same result over and over again). In other words, it makes sense you get different results on GCC and MSVC. – atlaste May 27 '15 at 05:56
  • But why value of v is changing.It's memory location is different right. – prabhudas May 27 '15 at 06:09
  • @Prabhudas That's undefined behaviour. You can't expect any particular outcome from a program with UB. All bets are off. – juanchopanza May 27 '15 at 06:09
2

You are calling the function:

void init_graph(int arr[10][10], int v);

However your code is:

int arr[v][v];
init_graph(arr,v);

This causes undefined behaviour if v is not 10. The C11 standard clause is 6.5.2.2/6:

If [...] the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.

Arrays of dimension X are only compatible with arrays of dimension Y if X == Y. (Bear in mind that the innermost dimension is "lost" due to the array as function parameter syntax quirk, so the innermost dimension can differ without breaking compatibility).


To fix this you should include the size in the array dimension in the function prototype:

void init_graph(int v, int arr[v][v]);

and similarly for the other functions.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
1

In main() you define your array to be of size [v][v], but init_graph() takes an array of size [max][max]. You need to make these the same. I suggest changing main() since all your other functions also use max as the array size.

What happens is that when v is 5, your [5][5] array is laid out as 25 consecutive ints. But the function thinks the array is size [][10], with row size of 10 ints. So the moment you write to any element past [2][4] (the 25th element), you are writing past the end of the array and clobbering your stack. This is because your array in main() was defined as a local variable and is therefore located on the stack. In your case, the stack also contained the value of v, and it got overwritten with a 0. The reason the other compiler worked is probably because it located v before the array in memory instead of after it, so with that compiler it didn't happen to clobber v.

According to the other answers, calling the function with an incorrect argument invokes "undefined behavior" but I find that to be a lazy explanation ("anything can happen"). I hate it when people say that because any compiled program is a known quantity any you can determine exactly what the "undefined" behavior actually is (just step through it with a debugger). Once you learn what is going on and where your variables are located, you will start to intuitively understand when memory is getting corrupted and what code could possibly be responsible for it.

JS1
  • 4,745
  • 1
  • 14
  • 19
  • 1
    It would be nice if you explained why this could make a difference. E.g. what does a function parameter `int arr[max][max]` really mean? – juanchopanza May 27 '15 at 05:34
  • @juanchopanza In simple terms: It means you're reading past the bounds of the array, which means it's undefined behavior. C/C++ has no bounds checking, so you're just looking at arbitrary memory. – atlaste May 27 '15 at 05:45