在C中的函数调用内为指针分配内存

时间:2014-09-09 04:17:02

标签: c

我做了一个示例程序来说明问题。在test中,我为foo分配内存以存储两个整数。然后,我将每个整数设置为一个值,然后我打印它们。非常简单,除非我只能在main内部为整数赋值 - 当我在test内部执行时,它将无效。


此代码有效:

#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;
}

输出:

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

此代码不会:

#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;
}

输出:

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

那么,发生了什么? This answer非常有用(或者我认为至少是这样),但它没有解决为什么分配在main而不是test中工作。

这是我对第二个例子中的代码应该如何工作的理解(我在代码中加上脚注来表示我在这里引用的行):

  1. 该程序从main开始。我创建了整数点foo,它被分配了一个4字节的内存块(为了简单起见)地址1000

  2. 我将foo的引用发送到函数test。因此,它以1000作为参数传递。

  3. foo分配一个大小为8字节的内存块。

  4. 4存储在地址1000

  5. 3存储在地址1004

  6. 那么,我有什么误解,以及如何修复第二个示例中的代码,以便我可以在foo而不是test中初始化main

    谢谢!

3 个答案:

答案 0 :(得分:8)

优先!

你需要:

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

如果没有括号,*foo[0]*(foo[0]),实际上与(*foo)[0]相同,但 *(foo[1])写下谁知道在哪里。 *运算符绑定的次数不如[]运算符,因此您必须使用括号。

char *arr[];   // array of pointers to char
char (*arr)[]; // pointer to array of char

答案 1 :(得分:3)

试试这个,你会看到...操作顺序:

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

foo是指向int指针的指针。访问foo [1]会在main中的foo声明之后访问堆栈中的任何内容(没有,所以内存不好)。在使用array []运算符之前,需要取消引用。因此,parens应该修复它。

答案 2 :(得分:0)

像乔纳森指出的那样,这是运营商优先权的问题。 []优先于*,因此它被作为 int指针数组处理,而不是指向int数组的指针

另一种可能避免完全使用指针指针的解决方案是函数test()使用分配的内存返回内存地址,而不是接收foo作为参数。

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

int* test() {
    int *bar = malloc(2 * sizeof(int));
    bar[0] = 4;
    bar[1] = 3;

    return bar;
}

int main() {
    int *foo = test();

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

    free(foo);
    return 0;
}