我的问题是nums3数组,以及为什么最后一个for循环实际打印预期结果。据我所知,nums3数组包含指向结构的指针数组,但这些指针尚未初始化为结构的任何特定实例。但在这个for循环中,我可以分配值并看到预期的结果显示。
此外,我已经读到,使用malloc返回的指针,我可以在指针后面使用[index],并在分配的内存上迭代。我假设这个功能是利用它的类型乘以某个值的事实,它会自动进行除法,以知道这个内存块是如何分割的,从而知道前进到下一个索引的距离。但我仍然很困惑,为什么我在最后一个for循环中得到了预期的结果,而我还没有初始化或将这些指针指向任何特定的东西。
我知道,如果我添加**并将更改为->,那么我可以直接对这些指针进行操作,但现在有了代码,我可以使用。操作员访问结构成员。那么,如果nums3malloc行中没有**,那么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: %dn", n.num1);
n.num2 = 6;
printf("n.num2: %dn", n.num2);
n.num3 = 7;
printf("n.num3: %dn", 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("%dn", n[i]);
}
free(n);
}
运行此代码的结果:
杰森smith@jasonS-pc~/src/c$/a.exe01.2.3.4
杰森smith@jasonS-pc~/src/c$
问题:
当n是malloc返回的指针时,n[i]是如何工作的?C如何知道如何处理n[i]?C如何知道如何到达n[i+1]?它是否查看被调用的sizeof(),并除以它被相乘的次数,然后使用该结果来知道下一个单元格从哪里开始?
为什么n[i].num1=i;甚至编译?如果我所做的只是指定一个内存块,其中包含指向该结构的x个指针的大小(指针将小于该结构本身的大小),并且肯定没有初始化任何指向该结构实际实例的内容。为什么这不是语法或其他编译器生成的错误?.num1正在处理的单元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
,这是不可保证的。)
您说您没有分配足够的空间,因为sizeof(struct number)
=12而sizeof(struct number*)
=8
Malloc根据您要求的大小找到一个可用内存,并(如果成功)向您返回一个指向第一个地址的指针(这是虚拟内存)。如果你超过了创建的大小,你就进入了意外行为的领域。这意味着你要么可以从内存中写入和读取数据,要么就不能,即使你设法做到了,你也可能意外地覆盖内存中存储其他数据的区域。
在这种情况下,尽管打印通过时没有特殊行为,但当您尝试free(nums3)
时,您将收到一个错误。
此外,如果您颠倒nums2和nums3声明的顺序,并在nums3循环后打印nums2,您可能会看到这种数据损坏。
希望这对有帮助