我做了一个示例程序来说明问题。在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
中工作。
这是我对第二个例子中的代码应该如何工作的理解(我在代码中加上脚注来表示我在这里引用的行):
该程序从main
开始。我创建了整数点foo
,它被分配了一个4字节的内存块(为了简单起见)地址1000
。
我将foo
的引用发送到函数test
。因此,它以1000
作为参数传递。
为foo
分配一个大小为8字节的内存块。
4
存储在地址1000
3
存储在地址1004
那么,我有什么误解,以及如何修复第二个示例中的代码,以便我可以在foo
而不是test
中初始化main
?
谢谢!
答案 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;
}