1

Please explain (reason for the output) what happens as a result of running the two segments of code. Please explain their difference too. There are two versions of setArr(int, int) as explained below...

#include <stdio.h>

void setArr(int, int);

int *arr[10]; // array of 10 int pointers

int main(int argc, char *argv[]) {
    int i;

    setArr(0, 0);
    setArr(1, 100);
    setArr(2, 200);
    setArr(3, 300);
    setArr(4, 400);

    for (i = 0; i < 5; i++) 
        printf("arr[%d]: %d\n", i, *arr[i]);   /* should be 0,100, 200,300,400 */

    return 0;
}

Versions of setArr

Version A

void setArr(int index, int v) {
    int i = v; 
    *arr[index] = i;
}

Output: Segmentation fault (core dumped)

Version B

void setArr(int index, int v) {
    int i = v;
    arr[index] = &i;
}

Output:

arr[0]: 400
arr[1]: 32748
arr[2]: 32748
arr[3]: 32748
arr[4]: 32748

I presume the values from running Version B are just random values.

I am fairly new to pointers I have knowledge in Java, so please explain it as beginner friendly as you can :)

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Janick C.
  • 21
  • 2
  • 1
    Why you are using an array of `int` pointers when your intention is just to set `int`-s? – Inian Jul 17 '19 at 06:02

3 Answers3

5

You are hitting a lot of undefined behavior scenarios, but I will explain what is likely happening.

arr is an array of 10 pointers to integers.

int * arr[10]; // array of 10 int pointers

And when declared as a global variable, all of those pointers are going to be zero-initialized - so hence, it's an array of 10 NULL pointers.

So this line in version A, is dereferencing the address at arr[index]:

* arr[index] = i;

Is effectively saying this:

*(NULL) = i;

And that will certainly crash consistently.

In Version B, you have it as:

    int i = v;
    arr[index] = &i;

So now you are correctly assigning a pointer to a slot in the array. However that address getting assigned is to a local stack variable, i, which goes out of scope as soon as the function returns. So when you print the value at that address, it's most certainly been clobbered from other calls writing on top of the stack. (Or technically this "undefined behavior" of accessing a memory address of a stack variable that has gone out of scope.)

Better:

void setArr (int index, int v){
    arr[index] = malloc(sizeof(int));
    *arr[index] = v;
}

The above allocates memory for the address that you want to copy that value into. You're on your own for how to free that memory.

Alternatively:

Just declare arr as an array of integers instead of pointers:

int arr[10];
void setArr (int index, int v){
    arr[index] = v;
}

And then print normally without the * deference thing on arr.

printf("arr[%d]: %d\n", i, arr[i]);
selbie
  • 100,020
  • 15
  • 103
  • 173
1

Version A says "the contents of an undefined pointer equals i" - undefined behavior = crash. Basically you are trying to write to some unknown location in memory.

Version B says "Some pointer = some address" - still undefined behavior as &i goes out of scope, but it is still an address and so it "kind of works". Here you are writing to "good" memory locations, but reading from bad ones.

John3136
  • 28,809
  • 4
  • 51
  • 69
  • 1
    Nitpick: "...undefined pointer equals i" is not correct. The pointer is defined and the pointer value is NULL (due to `arr` being a global variable) – Support Ukraine Jul 17 '19 at 06:15
  • The assignments are perfectly kosher in the second case; it is using the result of the assignments after the function that does the assigning exits that leads to UB. If the single pointer initialized in Variant B was used to print the data in the `setArr()` function, or in a function it called, there'd be no problem. This is, however, nitpicking — in the code shown, the end result is UB in the printing code. – Jonathan Leffler Jul 17 '19 at 06:45
-1

in first case, you have defined the "array of pointers" to integer. They are not integer pointers. Either you will have to allocate memory (preferably using melloc/calloc functions) before storing any value to them OR you can define the array of integer like this: int (*a)[10]

The following link may show you some idea about it: Difference between *ptr[10] and (*ptr)[10]

In second case, you are saving the address of integer into integer pointer, which is ok, but int i is local variable to function setArr(). This will therefore, the value of int i will be dereferenced every time the function setArr() exits. Therefore you are getting undefined behavior for 2nd case. Either you can use static int i OR use global variable (not preferred) OR use pointer to integer assignment.

Workarea
  • 7
  • 4