【问题标题】:How to pass the 2D array point to the other functions?如何将二维数组点传递给其他函数?
【发布时间】:2020-08-02 09:06:58
【问题描述】:

我有一个问题。我想将我自己的二维数组传递给pass 函数。在那个函数中,我将更改我自己的数组。所以,有一个return。我确切知道的是编译器可以接受代码攻击。但是,我不知道为什么。当我将int (* aaa)[3];main 函数中取出时,它运行良好。但是,当它在main 内时,会抛出unable to use the uninitialized aaa 的异常。我想知道为什么会发生这种情况。

int* pass(int (*a)[3]) {
    a=(int*)malloc(sizeof(int*)*2);
    a[0][1] = 1;
    a[0][2] = 2;
    return a;
}
int (* aaa)[3];
int main() {
    aaa = pass(aaa);
    printf("%d", aaa[0][2]);
}

这可以工作。

int* pass(int (*a)[3]) {
    a=(int*)malloc(sizeof(int*)*2);
    a[0][1] = 1;
    a[0][2] = 2;
    return a;

}

int main() {
    int (* aaa)[3];
    aaa = pass(aaa);
    printf("%d", aaa[0][2]);
}

但是,这行不通。

【问题讨论】:

  • 去掉变量名周围的(,) 和指针指示器*。虽然(datatype*) variablename 很好.. 但仍然有点括号过分。
  • @OlSen 他们不是不必要的。它们改变了声明的含义。
  • 确实.. 不就是一个匿名函数声明吗?
  • @OlSen 不。 OP 正在声明一个指向三个整数数组的指针。如果没有括号,它将是一个包含三个指向 int 的指针的数组。
  • 当然不行。 a=(int*)malloc(sizeof(int*)*2); 为两个指针分配存储空间。 a[0][1] = 1; 毫无意义。 int (* aaa)[3]; 是一个指向数组的指针 int[3],您在任何地方都找不到int[3] 数组。

标签: arrays c malloc point


【解决方案1】:

int (* aaa)[3]; 出现在任何函数之外时,aaa 会自动初始化为空指针。当它出现在函数中时,它没有被初始化。

代码aaa = pass(aaa);aaa 传递给名为pass 的例程。这是aaa 值的使用。当aaa 被初始化后,就可以了。但是,当 aaa 未初始化并且您尝试传递其值时,C 标准未定义该行为。这就是编译器警告您的内容。

接下来,让我们检查一下这段代码:

int* pass(int (*a)[3]) {
    a=(int*)malloc(sizeof(int*)*2);
    a[0][1] = 1;
    a[0][2] = 2;
    return a;
}

此代码从不使用传递给它的a 的值。当一个函数被调用时,它的参数 a 在这种情况下被赋予一个值(来自调用者传递的参数)。这个参数是一个独立于参数的变量。用a=(int*)malloc(sizeof(int*)*2);a 赋值不会改变调用例程中aaa 的值。因此,这段代码为a 分配了一个新值,而不使用旧值。

因此,例程不需要传递给它的参数。可以改为使用局部变量,如下所示:

int (*pass(void))[3] {
    int (*a)[3] = malloc(2 * sizeof *a);
    a[0][1] = 1;
    a[0][2] = 2;
    return a;
}

这里的void 表示pass 不接受任何参数。

请注意,我将 malloc(sizeof(int*)*2 更改为 malloc(2 * sizeof *a)sizeof(int*)*2 是错误的,因为它为两个指向 int 的指针请求空间。但是a 指向三个int 的数组,因此,要获得其中的两个,您需要两个三个int 的数组的空间。那是2 * sizeof(int [3])。但是,将其写为malloc(2 * sizeof *a) 更容易,这意味着“a 指向的任何东西中的两个”。这也更好,因为它减少了出错的频率:即使a 的声明被更改,这个sizeof *a 也会自动调整,无需编辑。对于sizeof(int [3]),对a 声明的任何编辑都需要对sizeof 进行另一次编辑。

另外,我删除了(int*) 以转换malloc 的结果。在 C 中,void *,即 malloc 返回的类型,将自动转换为分配给它的任何对象指针类型。不需要显式转换,使用显式转换可以掩盖某些错误。 (但是,如果你用 C++ 编译器编译程序,它会抱怨缺少强制转换,因为 C++ 中的规则不同。)

由于该函数返回一个指向三个int 数组的指针,而不是指向int 的指针,因此我将其声明更改为int (*pass(void))[3]

通过这些更改,程序可以是:

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

int (*pass(void))[3]
{
    int (*a)[3] = malloc(2 * sizeof *a);
    a[0][1] = 1;
    a[0][2] = 2;
    return a;
}

int main(void)
{
    int (*aaa)[3] = pass();
    printf("%d\n", aaa[0][2]);
}

【讨论】:

  • ` int* pass(int (a)[3]) { a=(int)malloc(sizeof(int*)*2); a[0][1] = 1; a[0][2] = 2;返回一个; } `这里虽然没有使用aaa,但是`return a`会返回一个已经分配好的地址给aaa。所以,aaa可以读取aaa[0][2],对吧?
【解决方案2】:

也许这有助于您了解 C 在数组方面是“灵活的”。
因为在第一部分中,假定的数组声明由 initAAA 函数的 malloc 中的 datalen 给出,并返回指向分配的内存。并且仍然在 for 循环中,我们可以通过索引访问数据。

main 的第二部分仅声明 same 数据 'bbb' 与第一个 'aaa' 但这次不是指针,并且用零 (0) 初始化数据字段是通过大括号。 {}。遍历所有索引的无聊 for 循环并将每个数据字段设置为 int 0 也可以。但是谁想要更多的代码呢?

#include <stdio.h>
#include <string.h>

int *initAAA(int *p, uint entrys) {
    size_t datalen = entrys * sizeof *p;
    p = malloc(datalen); // p is a pointer here.
    // copy character '0' starting at address of p up to datalen addresses
    // easier then writing a for loop to initiate safely.
    memset(p, 0, datalen);  // defined in string.h
    return p;
}

int main(void) {
    const uint maxAssets = 3;
    const uint entrysPerAsset = 2;
    int *aaa = NULL; // always a good idea, to set pointers to NULL before allocating memory for it. Because you can check if (aaa==NULL) initAAA(...
    uint entrys = maxAssets * entrysPerAsset;
    aaa = initAAA(aaa,entrys);
    printf("address:%p items:%d \n",aaa, entrys);
    for (uint i = 0; i < entrys; i++) {
        printf("%d ", aaa[i]);
    }
    free(aaa); // malloc without free, bad idea!

    printf("\n---\n");
    
    int bbb[maxAssets][entrysPerAsset] = {0,0,0,0,0,0};
    for (uint a = 0; a < maxAssets; a++) {
        for (uint e = 0; e < entrysPerAsset; e++) {
            printf("%d ", bbb[a][e]);
        }
    }
    // bbb does not need free(bbb); because it is released with the function end.
    // and yep, there was no malloc for bbb. so we are done.
}

顺便说一句。欢迎来到 C.

【讨论】:

  • 非常感谢。但我认为在第一部分中,您的 aaa 只是一个一维数组指针。对吗?但是,它有助于我理解 2- D 数组。
  • size_t datalen = entrys * sizeof(p); p = malloc(datalen); 计算大小不正确。应该是entrys * sizeof *p
  • int bbb[maxAssets][entrysPerAsset] = {}; 有两个问题。根据 C 2018 6.7.9 1,初始化器列表在 C 语法中可能不为空,并且 C 标准没有定义初始化可变长度数组,这是因为 maxAssets 不是 C 标准定义的常量。
猜你喜欢
  • 2020-11-01
相关资源
最近更新 更多