能够从未初始化的指针阵列到结构打印预期结果 - 困惑

时间:2016-08-04 04:55:46

标签: c arrays pointers struct malloc

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

另外,我已经读过malloc返回的指针,我可以在指针后使用[index]并迭代分配的内存。我假设这个特性正在使用它有一个类型乘以某个值的事实,并且它自动进行除法以了解这个内存块是如何分开的,因此可以推进到下一个索引的距离。但是,当我还没有初步确定或指出那些特定的指针时,我仍然很困惑为什么我会在最后一个for循环中获得预期的结果。

我知道如果我要添加**并将更改为 - >那么我可以直接对这些指针进行操作,但现在使用代码,我可以使用。运营商访问结构成员。那么,如果没有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 [i]如何使用n作为malloc返回的指针? C如何知道如何处理n [i]? C如何知道如何到达n [i + 1]?它是否会调用sizeof()被调用并除以它乘以多次并使用该结果来知道下一个单元格的起始位置?

  2. 为什么n [i] .num1 = i;甚至编译?如果我所做的只是指定一个内存块,其中包含x指向结构的指针的大小(指针将小于结构本身的大小),并且当然没有初始化任何东西以指向此结构的实际实例。为什么这不是语法或其他编译器生成的错误?在.num1工作的单元n [i]中存在什么?现在没有[i]只包含没有有效地址的指针,因为它尚未初始化?我们怎么做到n [i] .num1 = i?是否有效的语法&#34;一些内存地址&#34; .num1 =&#34;某些值&#34;?

  3. 我知道这不是正确的方法,而且你们都提供了很好的信息,但我仍然对这个代码甚至编译的原因感到困惑。它对我来说没有意义。

2 个答案:

答案 0 :(得分:3)

一般情况下,如果您错误地访问内存,则不能指望任何。你不能期望得到正确的答案,你不能期望得到错误的答案。你不能指望你的程序崩溃,你不能指望它运行。同样,它可以做任何事情。

这里的错误是你分配了一个指针数组,但后来选择了错误的类型来保存结果。

// 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,但不保证。{/ p>

答案 1 :(得分:0)

sizeof(struct number) = 8

的情况下,你没有分配足够的空格作为sizeof(struct number*) = 12,这是正确的。

Malloc根据您询问的大小找到一个空闲内存,并且(如果成功)返回指向第一个地址的指针(这是虚拟内存)。如果超过创建的大小,则输入意外行为领域。这意味着您将能够从内存中写入和读取数据,或者您不会,即使您设法这样做,也可能会意外覆盖存储其他数据的内存区域。

在这种情况下,虽然打印没有特殊行为,但当您尝试free(nums3)时,您将收到错误。

另外,如果你将在nums3循环之后颠倒nums2和nums3声明的顺序并打印nums2,你可能会看到这种数据损坏。

希望这是有帮助的