将指针传递给结构体数组时出错。

7
#include <stdio.h>
#include <stdlib.h>

struct Point {
    double x;
};

void test(struct Point **a, int len)
{
    int i;

    printf("a = %p\n", a);
    for (i = 0; i < len; ++i)
        printf("%f\n", a[i]->x);
}

int main()
{
    int i;
    int len = 4;

    struct Point *P;

    P = malloc(len*sizeof(struct Point));

    for (i = 0; i < len; ++i) {
        P[i].x = i;
        printf("%f\n", P[i].x);
    }
    printf("&P = %p\n", &P);
    test(&P, len);

    return 0;
}

我正在尝试将结构体数组传递给一个函数(我想传递指向数组的指针,而不是复制)。当我尝试在函数内部使用数组时,我遇到了访问冲突。正确的做法是什么?我做错了什么?a == &P,所以应该可以工作,对吗?


1
但是 P 已经是一个指针,它指向分配的内存(数组)的第一个元素。通过直接传递指针,您不会复制任何东西,只会复制实际的指针。 - Some programmer dude
5
printf("%f\n", (*a)[i].x); - BLUEPIXY
5个回答

5
为什么你需要一个struct Point **?你可以重写成:
void test(struct Point *a, int len)
{
   //some stuff
    printf("%f\n", a[i].x);

}

然后像这样调用

 test(P, len);

我认为这种方式符合要求:

我想传递一个指向数组的指针

这也满足要求#.


(#) 注意: 严格来说,我们在这里传递的是指向数组第一个元素的指针,然而这种行为相当。感谢@alk先生的评论。


谢谢,所以只是为了确保,在函数中不会复制任何内容,并且我对数组所做的任何更改仍然在函数返回后保持不变? - user1801359
挑剔一下:展示指向数组第一个元素的指针是通过传递来完成的。这与指向数组的指针不同,后者将是 struct Point (*pa)[len] - alk
@alk 非常正确,先生。您能建议适当的措辞修改我的回答吗? - Sourav Ghosh
尽管使用 struct point ** 没有任何好处,但 OP 代码中唯一的错误是 a[i]->x - haccks
@haccks 先生,我认为OP更关心“不要复制”这一部分,而不是数据类型本身。所以,我只是试图用简化的方式来表达它。 :-) - Sourav Ghosh

3
&p传递给函数test意味着您正在传递指向类型为struct Point *的一个元素的数组的第一个元素的指针。因此,只有a [0]是有效的(因此a [0] -> x ),所有其他a [i]都是越界访问。这将引发未定义的行为。
test函数中将a [i] -> x 更改为a [0] [i] .x (* a) [i] .x
在这种情况下使用指向指针不值得。如果要在函数中修改传递的指针并且希望在调用者中看到该修改,则可以使用这种方法。

3
更好的写法是(*a+i)->x - W.F.
2
@WojciechFrohmberg,难道不应该是JoachimPileborg在上面的评论中建议的吗? - Spikatrix
2
@CoolGuy 如果我们有 struct Point **a,那么 (*a) 是指针解引用,[i] 是从地址中读取值,因此也是指针解引用... 这意味着在这两个操作之后,我们得到了一个类型为 struct Point 的结果,因此我们不能像获取 struct Point * 一样访问它... - W.F.
1
@WojciechFrohmberg,我认为你是对的。所以,Joachim的评论是错误的,因为他三次取消引用指针? - Spikatrix
@CoolGuy;是的,我认为他当时和我一样很困惑。 - haccks
显示剩余4条评论

1
数组应该使用参数struct Point *a传递。 当你增加a指针时,指针会移动sizeof(struct Point)
void test(const struct Point *a, int len)
{
    ...
}

1
其他答案提供了更好的替代方案。但是我会把这个放在这里,帮助任何人(包括我自己)理解为什么这是错误的。

enter image description here                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             


0
我想传递一个数组指针, 按照您的要求,可以这样做:
void test(size_t len, struct Point (*a)[len])
{
  size_t i;

  printf("a = %p\n", (void *) a);

  for (i = 0; i < len; ++i)
    printf("%f\n", (*a)[i].x);
}

然后像这样调用:

size_t len = 4;
struct Point * p = malloc(len * sizeof *p);

for (i = 0; i < len; ++i) {
    p[i].x = i;
    printf("%f\n", p[i].x);
}

printf("p = %p\n", (void *) p);
printf("&p = %p\n", (void *) &p);

test(len, &p);

您也可以通过采用Sourav Ghosh答案中提出的方法(循环遍历数组元素)来实现相同的功能。然后,您将传递指向数组的第一个元素的指针,而不是指向数组本身的指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接