在函数中解除引用数组指针

时间:2013-06-04 19:56:41

标签: c arrays pointers

如何取消引用指向数组的指针以获取存储在其中的值?例如:

void testFunction(int **test){
  printf("%d", *test[1]);
}

int main()
{   int test[10];
    test[1] = 5;
    testFunction(&test);
    return 0;
}

我收到错误。谁能解释一下?

3 个答案:

答案 0 :(得分:3)

  

如何使用指向数组的指针来获取存储在其中的值?

您使用*运算符,与每个指针一样。 (哦,注意运营商的优先权!)

void foo(int (*arr)[5])
{
    printf("%d\n", (*arr)[0]);
}

int main()
{
    int arr[5] = { 0, 1, 2, 3, 4 };
    foo(&arr);
    return 0;
}

答案 1 :(得分:2)

您的代码会生成有关传递给函数的不兼容类型的诊断信息。例如,GCC抱怨:

prog.c: In function 'main':
prog.c:9: warning: passing argument 1 of 'testFunction' from incompatible pointer type

您应该注意编译器发出的所有诊断信息,并确保理解它们,并采取适当的措施来解决它们。对于这个特定的一个,如果你打算传入一个指向数组的指针,你需要编写你的函数来接受这样的事情。然后,当您取消引用指针时,您有一个数组。所以,你可以像访问它一样访问它。

void testFunction(int (*test)[10]){
  printf("%d", (*test)[1]);
}

[]的优先级高于*,因此括号既需要函数参数参数,也需要访问printf()中的值。当指向int[10]的指针被引用时,结果值是test中定义的数组main的第一个元素的地址。然后[]操作访问数组的第二个元素,并获得您期望的值。


如果您注意到下面的断言始终为真,您可能更确信使用int **test对指向数组的指针是错误的:

int test[10];
assert(&test == (void *)test);

如编译器警告所示,指向int的指针与指向int[10]的指针不同。指向的类型确定取消引用所产生的类型。

所以:

int test[10] = { [1] = 5 };
testFunction(&test);

这会将test的地址传递给testFunction。变量的地址对应于它在内存中的位置。这对于数组来说并没有那么不同,但是数组变量的内存中的位置是其第一个元素的地址。因此,上面&test返回的地址与test单独返回的地址相同。

当您将此指针值视为指向inttestFunction指针的指针时,会产生灾难性后果。首先,请注意您忽略了正确的运算符优先级,因此第一个取消引用是:

test[1]

由于您声明test参数是指向int指针的指针,因此testsizeof(int *)的地址增加int *,并将结果视为{ {1}}。然后,再次取消引用:

*test[1]

现在取test[1]的值并再次取消引用它以尝试获得int。但是,test[1]返回的地址与test中定义的数组main没有任何关系,并且您正在访问一个完全没有意义的内存位置。

即使您注意指针指向int参数类型的指针的优先级,也会产生类似的问题。

(*test)[1]

现在,指向int[10]的指针被视为指向int指针的指针首先被引导。这会导致sizeof(int **)test数组的前main个字节被视为指向int的指针。此时这已经是一个荒谬的值,但是现在数组解除引用会将此值增加sizeof(int)个字节,并在尝试获取int时取消引用该值。

答案 2 :(得分:-1)

另一个用户给出了一个如何通常已经完成的示例,但是如果你坚持传递一个int **,那么由于运算符优先级,语法就像:

void testFunction(int **test){
  printf("%d", (*test)[1]);
}

int main()
{   int test[10];
    test[1] = 5;

    int *testptr= &test[0];  // or int *testptr= test;
    testFunction(&testptr);  // this passes an int **
    return 0;
}

但是在c中,数组的名称是指向数组元素的指针,因此更常用int * ptrtest和ptrtest [1]。