1

我正在尝试发送一个指向函数的指针,但该指针是指针数组的一部分

void func(A **pa)
{
     return;
}


A *pa;
pa=(A*)malloc(2*sizeof(A));

所以,数组中的第一项pa[0]很容易发送(因为它是指针指向的地方)

func(&pa);

但是现在我卡住了,我该如何发送第二个项目?pa[1]

我尝试了类似的东西,func(&pa + 1*sizeof(A)); 但似乎没有用。

4

4 回答 4

2

您正在寻找&pa[1]

func (&pa[1]);   // call function with second element of pointer array

顺便说一句,我不知道你是否要分配一个只有两个指针的数组,但如果你是,malloc 是错误的。它应该是

pa = malloc (2 * sizeof(A*));  // note the addition of * after "A"

您正在做的是分配两倍大小的 a A,可以想象它可能有数千个字节长。指向此类对象的指针不需要那么多空间。

此外,在 中C,不需要也不应该强制转换 的返回类型malloc()

于 2012-11-28T06:23:14.277 回答
2

如果你想传递一个指向 A 数组的指针,你应该这样做:

func(&pa[0]); 
func(&pa[1]);

但是如果它是一个数组,你不应该只传递一个指向数组本身的指针和数组的大小吗?这基本上意味着只有第一行。

如果您想将指针传递给指针数组,您应该完全不同:

A **pa;
pa=(A**)malloc(2*sizeof(A*));

但是您还必须对每个 A 进行 malloc 并相应地更改 Func 。

另请注意,func(&pa + 1*sizeof(A))由于指针数学,这不起作用:您只需要这样做func(&pa + 1),编译器会处理其余的事情以获取数组中的第二个成员。

于 2012-11-28T06:36:53.817 回答
2

注意:此答案已更新,以反映四个小时前 OP(原始海报)@hudac 的澄清。提出的问题既有效又非常有趣。话虽如此,可能有一些方法可以简化 OP 的代码,我会在提供原始问题的答案后查看这些方法。

首先,根据 OP 最近的澄清,我将通过给出 A 和 func 的示例定义,尝试使问题的代码更加具体:

typedef struct { int x; int y;} A;

void func(A **ppa)
{
   printf("(%d,%d)\n",(*pa)->x,(*pa)->y);
}

然后,我将给出一些代码,为问题和答案提供适当的上下文:

void main() {
    A *pa;  
    pa = (A*) malloc(2 * sizeof(A));

    pa[0].x = 3;    pa[0].y = 4;
    pa[1].x = 13;    pa[1].y = 42;

    func(&pa);      
    //the answer to the question goes here
}

目前的问题要求一种方法将指针传递给指向动态分配的 A's 数组的第二个pa元素的指针。OP 尝试过,成功地传递了指向pa( func(&pa);) 的第一个元素的指针的指针,尝试使用指针算法传递指向第二个元素的指针的指针,这当然没有按预期工作。鉴于 OP 的代码,给出的答案都没有接近正确!事实证明这是一个非常有趣的问题,因为有func期望 A ** 而不是 A * 会使事情变得比它们必须的复杂得多。在不了解 OP 遇到的问题的情况下,可以使事情变得更简单,但这无法深入了解为什么要正确地获得该指针算术如此困难(实际上是不可能的)。

重温基础知识的一个小弯路:如果你有一个赋值,你有一个左值(左侧表达式)和一个右值(右侧表达式);左值是有地址的东西,右值有一个值,赋值存储在左值的地址中。一个例子:x = 5; 一个表达式可能有一个左值和一个右值(例如 x),或者它可能只有一个右值(例如 5)。运算符 & 仅适用于左值,即具有内存地址的事物,即诸如 x 之类的事物,但不适用于诸如 5 之类的事物。

回到问题:pa 是 A * 类型,而 func 需要 A ** 类型的参数。OP 在弄清楚如何调用 func 以便它可以与 pa 的第一个元素一起使用时没有问题:

func(&pa);

请注意,我很难忍受将这段代码连同注释说这是对处理 pa 的第一个元素的 func 的调用。函数 func 需要在 pa[0] (aka * pa) 上操作,即 A 类型的东西,但是由于 func 的定义方式,我们传递了 A ** 类型的 &pa !!!稍后我将通过使用更合适的参数类型定义函数来解决这个问题。现在,我将尝试使用我所拥有的。

OP 和其他人发现很难调用 func 来处理 pa 的第二个元素的原因是,所需要的是一个指针表达式,其值包含一个内存的地址,该内存的地址是pa 的第二个元素。没有这样的指针表达式,因为 pa 的第二个元素的地址没有存储在任何地方。(抱歉,如果大写字母伤害了您的眼睛 :-) 我需要尽可能清楚地说明这一点!)通过指针算术访问 pa 的第二个元素,使用第一个元素的地址(这是 pa 持有的) .

这并不意味着不可能回答这个问题。这只是意味着答案将出乎意料并且令人讨厌。因此,假设问题不允许我们在 main() 中引入另一个变量,我们只需更改 pa 以便调用 func,然后将其更改回来以便能够使用 pa 而不会出现令人讨厌的意外稍后在 main() 中。

pa++; func(&pa); pa--;

是对OP问题的答案。当前在此处发布的其他答案试图回答不同且更简单的问题。但是最初的问题要有趣得多,现在它有了答案:-) 但我觉得比答案更有趣的是我强调使用大写字母的观察。

为了恢复理智,我们需要重新审视 func 定义中所做的选择。

如果我们只想访问存储在数组中的 A,我们可以考虑完全消除对指针的依赖。

typedef struct { int x; int y;} A;
void bar(A a)
{
   printf("(%d,%d)\n", a.x, a.y);
}
void main() {
    A *pa;  
    pa = (A*) malloc(2 * sizeof(A));

    pa[0].x = 3;    pa[0].y = 4;
    pa[1].x = 13;    pa[1].y = 42;

    bar(pa[0]);      
    bar(pa[1]);
}

我们可能要考虑让函数采用 A * 参数而不是普通 A 的原因有两个:1. 如果函数需要修改指向的 A 和/或 2. 如果 A 恰好是一个大结构并且我们不希望每次调用我们的函数都会导致将一大块内存复制到堆栈中。

typedef struct { int x; int y;} A;
void foo(A *a)
{
   int tmp = a->x;
   a->x = a->y;
   a->y = tmp;
}
void bar(A a)
{
   printf("(%d,%d)\n", a.x, a.y);
}
void main() {
    A *pa;  
    pa = (A*) malloc(2 * sizeof(A));

    pa[0].x = 3;    pa[0].y = 4;
    pa[1].x = 13;    pa[1].y = 42;

    foo(&pa[0]); //or alternatively: foo(pa);
    bar(pa[0]);  //or alternatively: bar(*pa);

    foo(&pa[1]); //or alternatively: foo(pa + 1);
    bar(pa[1]);  //or alternatively: bar(*(pa+1));
}

可能对 OP 有所帮助的另一个注意事项是,在执行指针算术时,指针的类型起着重要作用。所以 pa + 1 的数值等于 pa 的数值加上 sizeof(A)。(这与尝试使 func 与 pa 的第二个元素一起使用以下调用失败有关:func(&pa + 1*sizeof(A)))

对 OP 的最后说明:如果您不想更改 func 的签名,因为您计划在 func 中获取一个 A** 指针并用它做一些有趣的事情,例如为其分配另一个指针(例如指向一个新的 malloc( )-分配的内存块),你会走进一个雷区!请检查我对另一个问题的回答,我相信您会发现相关问题:为什么 line2 中的 free 使 memcpy 什么也不做?malloc 之前是免费的吗? 这个故事的寓意是指针很有用,但概念复杂性和错误的可能性随着每个 * 呈指数增长(并且通常有更好的选择):-)

于 2012-11-28T09:15:06.117 回答
1

尝试这个 :

func(&pa[0]); // for 1st object 
func(&pa[1]);// for 2nd object

pa将为您提供 A 数组的地址。 &pa将为您提供整个数组的地址。

方法,

A * ptr;

ptr = pa ;// increment `ptr` will give you next element in same array
ptr = &pa ;// increment `ptr` will give you the next array of that type

还将函数func签名更改为

void func(A *pa)
{
     return;
}

==================================================== ==========

如果要将指针数组传递给func

这样做:

A **pa = malloc(2*sizeof(A*));

然后像这样发送

func(&pa[0]);
func(&pa[1]);

并且func将是

void func(A **pa)
{
     return;
}
于 2012-11-28T06:23:56.253 回答