【问题标题】:returning pointer to pointer array of a struct返回指向结构的指针数组的指针
【发布时间】:2014-12-30 11:44:21
【问题描述】:

我正在开发一个包含指向结构的指针数组的 C 程序。 首先结构看起来像这样:

typedef struct
{
    int ID;
    char Name [20];
} rec;

然后我有一个创建这些结构之一的函数:

struct rec* addEntry(){
    rec *temp;
    temp = malloc(sizeof(rec));
    printf("Please give me an ID number\n");
    scanf("%d", &temp->ID);

    printf("Now give me a name, maximum size for this is 20 characters\n");
    scanf("%s", &temp->Name);
    return temp;
}

现在这个函数可以正常工作了,它创建结构并返回指向该结构的指针 然后我有另一个函数,它创建一个指针数组并用指向结构的指针填充它:

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    printf("ID in main : %d\n", pointerArray[0]->ID);
    printf("Name in main : %s\n", pointerArray[0]->Name);
    printf("ID in main : %d\n", pointerArray[1]->ID);
    printf("Name in main : %s\n", pointerArray[1]->Name);
    pointerArray = malloc(sizeof(rec*)*2);
    return pointerArray;
}

为了检查发生了什么,我打印了存储在指针数组中的位置的值。 此时指针数组中的值是正确的。

但是现在我需要为这个指针数组分配空间并返回一个指向这个指针数组的指针,这就是我卡住的地方。

malloc 行给了我一个错误:

error: incompatible types when assigning to type 'struct rec *[(sizetype)(size)]' from type 'void *'

现在澄清我不能使用链表,我必须使用指针数组。 要添加到我的主循环中,我在以下代码中还有另一个错误:

rec *pointerArray[2];
pointerArray = returnPointerToPointerArray(2);
printf("ID in main : %d\n", pointerArray[0]->ID);
printf("Name in main : %s\n", pointerArray[0]->Name);

这给了我以下错误:

error: incompatible types when assigning to type 'struct rec *[2]' from type 'struct rec *'

欢迎任何帮助。

提前致谢,伊尔瓦

【问题讨论】:

  • 'pointerArray = malloc(sizeof(rec*)*2);'因为您已经尝试在其中存储东西,所以无法正常工作,而且对于您的意图来说已经太晚了。 'pointerArray' 是一个自动存储数组,不是指针,所以不能 malloc。
  • 但是如果我返回一个指向该数组的指针,那么该数组不会消失,因为它是在本地声明的?
  • 您已经在这两个函数中创建了指向 struct 的指针,而没有在使用它们之前将它们初始化为指向任何地方。我写了下面的例子(第一次写的时候有错误,现在已经测试过了)
  • 你能告诉用户如何利用你的缓冲区溢出,真是太好了。
  • struct rec 未在任何地方定义。如果你写struct rec *,那么它定义了一个新类型,它与rec 不兼容。

标签: c pointers struct


【解决方案1】:

我发现了两个问题:

首先,在将结果复制到pointerArray 之前返回。

pointerArray = malloc(sizeof(rec*)*2);
return pointerArray;

我的建议是

struct rec** returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    printf("ID in main : %d\n", pointerArray[0]->ID);
    printf("Name in main : %s\n", pointerArray[0]->Name);
    printf("ID in main : %d\n", pointerArray[1]->ID);
    printf("Name in main : %s\n", pointerArray[1]->Name);
    rec **pointerArray2 = malloc(sizeof pointerArray);
    pointerArray2[0] = pointerArray[0];
    pointerArray2[1] = pointerArray[1];
    return pointerArray2;
}

请注意,我已经更改了变量名。您确实在代码中犯了其他一些错误。

第二,

rec *pointerArray[2];

是一个指针数组。声明方式很简单:

rec **pointerArray;

顺便说一句,

pointerArray = returnPointerToPointerArray(2);

这一行应该使用法和声明不匹配。

更新:

在我的回答中发现了一些错误。你正在返回一个指针数组。

【讨论】:

  • 将记录 *pointerArray;不只是创建一个指向类型rec 的指针?而不是一个指向类型 rec 的指针数组?
  • @Ylva 不明白你在担心什么。类型系统中的指针和数组是相同的。 rec *pointerArray; 是指向某个地址的指针。通过pointerArray[1] 左右将其取消引用为数组。
  • pointerArray = returnPointerToPointerArray(2);确实不行,应该是pointerArray = returnPointerToPointerArray();
  • 是的,它可以做到这一点,这不是你需要的。
  • @Ylva 是的,我确实犯了错误。已经更新了。你应该使用双指针,因为你想指向一个数组。
【解决方案2】:

这段代码没有意义:

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    pointerArray = malloc(sizeof(rec*)*2);
    return pointerArray;
}

您正在定义一个指针堆栈数组并为它们分配struct rec 对象的堆地址,然后尝试将一个由两个指针组成的基于堆的数组分配给堆栈一个的地址。它永远不会编译。

由于您的函数旨在返回指向rec 类型对象的指针(我猜这将是数组中两个结构中的第一个),因此您应该首先在堆上为两个指针分配空间(因此使用双指针)然后填充它/返回它:

struct rec** returnPointerToPointerArray()
{
    rec **pointerArray;
    pointerArray = malloc(sizeof(rec*)*2); // Allocates 2 pointers
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    return pointerArray;
}

Live Example

您还应该在完成后释放分配的内存。

【讨论】:

  • 终于,看起来更像了。
  • struct recrec 是不同的类型,您只返回一个指向一个条目的指针。
  • @MattMcNabb 这也是正确的,对不起。我一开始没有检查返回类型。固定。
【解决方案3】:
typedef struct
{
    int ID;
    char Name [20];
} rec;

struct rec* returnPointerToPointerArray()
{
    rec *pointerArray[2];
    pointerArray[0] = addEntry();
    pointerArray[1] = addEntry();
    ...
    return pointerArray;
}

返回类型错误有两个原因。该函数返回一个rec *,同时声明它返回一个指向未定义struct rec * 的指针。 struct rec 类型与 typedef rec 不同!

其次,您应该将指向指针的指针返回到rec。当你返回数组时,数组名被转换成指向它的第一个元素的指针,它本身就是一个指针。

此外,您已将 pointerArray 声明为实际数组。您不能为数组分配新值,也不能返回指向局部变量的指针。 pointerArray 的生命周期在执行离开此函数时结束,因此指向它的指针将完全无用。使用这样的指针会导致未定义的行为

您需要首先为数组分配动态内存,填充数组,然后返回:

rec** returnPointerToPointerArray()
{
  rec **pA = malloc (2 * sizeof *pA);
  if (pA) {
    pA[0] = addEntry();
    pA[1] = addEntry();
    if (pA[0]) {
      printf("ID in main : %d\n", pA[0]->ID);
      printf("Name in main : %s\n", pA[0]->Name);
    }
    if (pA[1]) {
      printf("ID in main : %d\n", pA[1]->ID);
      printf("Name in main : %s\n", pA[1]->Name);
    }
  }
  return pA;
}

同样的问题:

rec *pointerArray[2];
pointerArray = returnPointerToPointerArray(2);
printf("ID in main : %d\n", pointerArray[0]->ID);
printf("Name in main : %s\n", pointerArray[0]->Name);

您不能为数组分配新值。您需要将pointerArray 定义为指向指针的指针

rec **pointerArray;
pointerArray = returnPointerToPointerArray(/*2*/);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    相关资源
    最近更新 更多