c - 能够从未初始化的结构指针数组打印预期结果 - 困惑

标签 c arrays pointers struct malloc

我的问题是 nums3 数组以及为什么最后一个 for 循环实际上打印了预期的结果。据我所知,nums3 数组包含指向该结构的指针数组,但这些指针尚未初始化为结构的任何特定实例。但在这个 for 循环中,我可以分配值并查看预期结果显示。

另外,我读到过使用 malloc 返回的指针,我可以在指针后使用 [index] 并遍历分配的内存。我假设此功能使用的事实是它有一个类型乘以某个值,并且它会自动进行除法以了解该内存块是如何拆分的,因此知道要前进到下一个索引多远。但是我仍然很困惑,为什么当我没有初始化或将这些指针指向任何特定的东西时,我在最后一个 for 循环中得到了预期的结果。

我知道如果我要添加 ** 并将 更改为 -> then 我可以直接对这些指针进行操作,但是现在有了代码我可以使用 .运算符访问结构成员。那么,如果没有 nums3 malloc 行中的 **,从 malloc 返回的指针究竟返回了什么?

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

#define ARRAY_MAX 5

int main(void)
{
    struct number {
        int num1;
        int num2;
        int num3;
    };

    struct number n;
    n.num1 = 5;
    printf("n.num1: %d\n", n.num1);
    n.num2 = 6;
    printf("n.num2: %d\n", n.num2);
    n.num3 = 7;
    printf("n.num3: %d\n", n.num3);

    struct number nums1[5];

    struct number* nums2 = malloc(sizeof(struct number) * ARRAY_MAX);
    struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);

    int x;
    for(x = 0; x <= 5; x++) {
        nums1[x].num1 = x;
        nums1[x].num2 = x;
        nums1[x].num3 = x;
    }

    int y;
    for(y = 0; y <= ARRAY_MAX; y++) {
        nums2[y].num1 = x;
        nums2[y].num2 = x;
        nums2[y].num3 = x;
    }

    for(y=0; y<=ARRAY_MAX; y++) {
        nums3[y].num1 = y;
        nums3[y].num2 = y;
        nums3[y].num3 = y;
        printf("%d ", nums3[y].num1);
        printf("%d ", nums3[y].num2);
        printf("%d \n", nums3[y].num3);
    }

这是我的问题的一个更简单的测试用例:

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

#define MAX 5

int main(void)
{
    struct number {
        int num1;
    };

    struct number* n = malloc(sizeof(struct number*) * MAX);

    int i;
    for(i=0; i<MAX; i++) {
        n[i].num1 = i;
        printf("%d\n", n[i]);
    }

    free(n);

}

运行这段代码的结果:

杰森·史密斯@jasonS-pc ~/src/c $./a.exe 0 1个 2个 3个 4

杰森·史密斯@jasonS-pc ~/src/c $

问题:

  1. 当 n 是从 malloc 返回的指针时,n[i] 如何工作? C 如何知道如何处理 n[i]? C 如何知道如何到达 n[i+1]?它是否查看正在调用的 sizeof() 并除以它被乘以多少次并使用该结果来了解下一个单元格的开始位置?

  2. 为什么 n[i].num1 = i;甚至编译?如果我所做的只是指定一个内存块,其中包含 x 个指向结构的指针的大小(指针将小于结构本身的大小)并且肯定没有初始化任何东西以指向该结构的实际实例.为什么这不是语法或其他编译器生成的错误? .nu​​m1 正在处理的单元格 n[i] 中存在什么? n[i] 现在不只是包含一个没有有效地址的指针,因为它还没有初始化吗?我们如何从那里到 n[i].num1 = i?执行“一些内存地址”.num1 = “一些值”的语法是否有效?

我知道这不是正确的方法,你们都提供了很好的信息,但我仍然不明白为什么这段代码可以编译。这对我来说毫无意义。

最佳答案

一般来说,如果你不正确地访问内存,你就不能期望任何东西。你不能指望得到正确的答案,也不能指望得到错误的答案。您不能指望您的程序崩溃,也不能指望它运行。同样,它无所不能。

此处的错误是您分配了一个指针数组,但随后选择了错误的类型来保存结果。

// This is wrong!
struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);

你想要这个:

struct number **nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
//            ^^

或者实际上,这种方式更好:

struct number **nums3 = malloc(sizeof(*nums3) * ARRAY_MAX);

然后你有一个(未初始化的)指针数组可以使用。例如,

for (int i = 0; i < ARRAY_MAX; i++) {
    nums3[i] = malloc(sizeof(*nums3[i]));
    nums3[i]->num1 = i;
    nums3[i]->num2 = i;
    nums3[i]->num3 = i;
}

或者...

for (int i = 0; i < ARRAY_MAX; i++) {
    nums3[i] = &nums2[i];
}

随便你。

(我们在这里假装 malloc() 不返回 NULL,这是无法保证的。)

关于c - 能够从未初始化的结构指针数组打印预期结果 - 困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38758743/

相关文章:

c - 来自 stdin 的 fgets() 导致段错误

c - OpenMP 基准测试 : Am I doing it right?

java - BufferedImage,转换为字节数组并返回后相同的图像,但灰度转换后不同

在 C 中即时更改标准输出(putch() 函数)

c - 复制矩阵的最后一个元素

C:排序方法分析

javascript - 使用 jquery 访问数组中的数据

c++ - 如何实现 array::max_size()?

c++ - 填充指向 vector 元素的指针的无序队列

c - 指向 C 函数的指针