发送指向函数的指针,而指针是指针数组的一部分

  • 本文关键字:指针 数组 一部分 函数 c
  • 更新时间 :
  • 英文 :


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

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

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

因此,数组pa[0]中的第一项很容易发送(因为它是指针指向的位置)

func(&pa);

但是现在我卡住了,我该如何发送第二件物品?pa[1]

我尝试了类似func(&pa + 1*sizeof(A));但它似乎不起作用。

您正在寻找&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的大小,可以想象它可能是数千字节长。 指向此类对象的指针不需要那么多空间。

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

如果你想传递一个指向 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),编译器负责其余的工作以获取数组中的第二个成员。

注意:此答案已更新,以反映四个小时前给出的澄清@hudac OP(原始海报)。 提出的问题既有效又很有趣。 话虽如此,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
}

目前的问题要求一种方法将指针传递给指向动态分配的 Apa数组的第二个元素的指针。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](又名 * pa)上运行,即类型 A 的东西,但由于 func 的定义方式,我们正在传递 A 类型 ** 的 &pa !! 稍后我将通过使用更合适的参数类型定义函数来解决此问题。 现在,我将尝试使用我所拥有的。

OP 和其他人发现很难调用 func 以处理 pa 的第二个元素的原因是,需要的是一个指针表达式,其值保存保存 pa 第二个元素地址的内存位的地址。 没有这样的指针扩展,因为 PA 的第二个元素的地址不存储在任何地方。(如果首都伤害了你的眼睛,请道歉:-)我需要尽可能清楚地说明这一点! 访问 pa 的第 2 个元素是通过指针算法,使用第一个元素的地址(这是 pa 所持有的)。

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

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 与以下调用的第二个元素一起工作的失败尝试有关:func(&pa + 1*sizeof(A

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

试试这个:

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

最新更新