【问题标题】:C passing a pointer to an array on the stackC将指针传递给堆栈上的数组
【发布时间】:2012-01-18 12:16:24
【问题描述】:

我很困惑是否有效(在 C 中)将指针传递给已按如下方式启动的数组(例如,在堆栈上的编译时):

int a[] = {1, 2, 3};

my_func(&a);


void my_func(int **a)
{
   int *tmp = *a; /* this statement fixes the problem */
   printf("%d %d %d", (*a)[0], (*a)[1], (*a)[2]); /*doesn't work */ 
   printf("%d %d %d", tmp[0], tmp[1], tmp[2]); /*does work */ 
}

当我使用 gdb 逐步执行此操作时,我无法从“内部”my_func 中“看到”任何值 (*a)[0] 等。例如

(gdb) p (*a)[0]
Cannot access memory at address 0x0

我在想我可能对堆栈而不是堆上的数组可以做什么和不能做什么有根本的误解?

我希望不是这样,因为我的单元测试可以很方便地在堆栈上声明数组,如示例中所示,但我需要测试期望指向 int 指针的函数。

请注意,我确实收到如下编译器警告:

 test_utility.c:499:5: warning: passing argument 1 of ‘int_array_unique’ from incompatible pointer type [enabled by default]
 ../src/glamdring2.h:152:5: note: expected ‘int **’ but argument is of type ‘int (*)[12]’

但我认为可以将 int *a[]**a 混合使用?也许不是?它们不相等吗?

【问题讨论】:

  • 如果你想将指针存储在堆栈上,你可以在存储它之前将它转换,并在你想使用它时再次转换它:ptr_int = (int)ptr 用于存储 ptr_intptr = (int*)ptr_int 用于用法。但我不确定这是否足以解决您的问题。
  • 传递对数组指针的引用是否有特殊原因?
  • @kenneth 是的 - 我将参数用作输入和返回值。
  • 我有一个修复,需要在 my_func 中进行适当的转换,int *tmp_a = *a;一切都开始工作了。
  • 基本上,正如 wildplasser 所指出的,我从右值中不知道我的左值。希望通过一些背景阅读来纠正这一点

标签: arrays c pointers heap-memory stack-memory


【解决方案1】:

在堆栈上声明一个数组并将其地址传递给函数是非常好的,只要该函数不尝试存储对数组的引用以供以后使用。

但不确定为什么要在参数中添加额外的间接性。为什么不直接声明my_func 以将int* 作为参数,然后简单地将a 作为参数传递?这不太可能混淆调试器。

【讨论】:

  • 这正是我的想法。我不明白为什么我不能取消引用 gdb 中的指针?
【解决方案2】:

您假设sizeof(int) == sizeof(void *)。这可能不是真的。我不确定这是否是您的问题的原因,但至少我会先添加一个运行时测试来断言假设,或者可能更好地从 int 更改为 pointer。

【讨论】:

    【解决方案3】:

    a[] 是一个数组,而不是一个指针(“不是左值”);在你的函数调用中

    func( &a);
    

    &a 衰减为指向 int 的指针; &a 不是指向 int 的指针。为什么? 没有指针可以指向。

    函数原型

    void func( int **p);
    

    需要一个指向 int 的指针,它不适合使用指向 int 的指针作为参数调用的函数,就像您所做的那样。

    更新:我不知道 OP 的意图是什么,所以这只是一个猜测......

    void my_func(int *a);
    
    int a[] = {1, 2, 3};
    
    my_func(a); /* note: this is equivalent to my_func( &a ); */
    
    
    void my_func(int *a)
    {
       printf("%d %d %d\n", a[0], a[1], a[2] ); 
    }
    

    【讨论】:

    • 你确定&aint* 类型吗?
    • 不是指向int的指针,它衰减为一个。 (因为没有指向的指针,指向数组的指针衰减为指向第一个元素的指针)
    • 是的,当然我的意思是腐烂。好吧,我不知道,但这很有意义,因为指向数组的指针确实是指向第一个元素的指针。反正我从来没有用过&a,所以从来没有真正考虑过。 +1。
    • @wildplasser 我想你可能已经在那里提供了答案,但我无法理解。你有没有机会用一个例子来说明你的观点?例如记住你所说的,需要什么代码才能让它工作?
    • @wildplasser 好的 - 所以你不能传入指向 a 的指针,然后希望在函数中取消引用以检索数组元素?
    【解决方案4】:
    printf("%p vs %p vs %p\n",&a,&a[0],a); 
    

    &a &a[0] 和a - 都是一样的——数组中第一个int的地址

    void my_func(int **a);
    int main(int ac, char *av[]) {
        int a[] = {1, 2, 3};
        int *p = a;
        printf("%p vs %p vs %p\n",&a,&a[0],a); //are all the same - the address of the first int in the array
        my_func(&p);
        return 0;
    }
    void my_func(int **a) {
        printf("%d %d %d", (*a)[0], (*a)[1], (*a)[2]);
    }
    

    http://www.ibiblio.org/pub/languages/fortran/append-c.html

    http://publications.gbdirect.co.uk/c_book/chapter5/arrays_and_address_of.html

    【讨论】:

      猜你喜欢
      • 2013-04-14
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 2011-04-19
      • 1970-01-01
      相关资源
      最近更新 更多