Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocating memory for a pointer inside a function call in C

Tags:

c

I've made an example program to illustrate the problem. In test I allocate memory for foo to store two integers. Then, I set each of these integers to a value, and then I print them. Pretty simple, except I can only assign values to the integers if I do it inside of main - it won't work when I do it inside of test.


This code works:

#include <stdio.h>
#include <stdlib.h>

void test(int **foo) {
    *foo = malloc(2 * sizeof(int));
}

int main() {
    int *foo;

    test(&foo);

    foo[0] = 4;  // <---
    foo[1] = 3;  // <---

    printf("foo[0]: %d\n", foo[0]);
    printf("foo[1]: %d\n", foo[1]);

    return 0;
}

Output:

foo[0]: 4
foo[1]: 3

This code doesn't:

#include <stdio.h>
#include <stdlib.h>

void test(int **foo) {
    *foo = malloc(2 * sizeof(int));  // 3.
    *foo[0] = 4;  // 4. <---
    *foo[1] = 3;  // 5. <---
}

int main() {
    int *foo;  // 1.

    test(&foo);  // 2.

    printf("foo[0]: %d\n", foo[0]);
    printf("foo[1]: %d\n", foo[1]);

    return 0;
}

Output:

foo[0]: 4        // This is only 4 because it was already
                 //   4 from running the previous example
foo[1]: 5308612  // And this is obviously garbage

So, what's going on? This answer has been very helpful (or I thought it was at least), but it doesn't address why the assignments work in main but not test.

Here's my understanding of how the code in the second example should be working (I've put footnotes in the code to indicate the lines I'm referring to here):

  1. The program starts at main. I create the integer point foo, which is assigned a 4-byte block of memory at (for the sake of simplicity) address 1000.

  2. I send a reference to foo to the function test. So, it is passed 1000 as its parameter.

  3. A block of memory two integers in size (8 bytes) is allocated for foo.

  4. 4 is stored at address 1000

  5. 3 is stored at address 1004

So, what am I misunderstanding, and how can I fix the code in the second example so I can do my initialization of foo in a test rather than main?

Thanks!

like image 885
Thomas Avatar asked Dec 19 '22 11:12

Thomas


1 Answers

Precedence!

You need:

(*foo)[0] = 4;  // 4. <---
(*foo)[1] = 3;  // 5. <---

Without the parentheses, *foo[0] is *(foo[0]), which is actually the same as (*foo)[0], but *(foo[1]) goes writing who-knows-where. The * operator binds less tightly than the [] operator does, so you have to use parentheses.

char *arr[];   // array of pointers to char
char (*arr)[]; // pointer to array of char
like image 145
Jonathan Leffler Avatar answered Feb 23 '23 01:02

Jonathan Leffler