我正在教朋友C.我们正在使用结构和指针,我给了他一个程序来试用他的电脑。我们将逐行解构程序,这样他就能理解结构和指针是如何协同工作的。在我结束时,我得到了这个结果:
astr中a的值是5
b在astr中的值是5.550000
astr中c的值为77
astr中的d值为888.888800
在他的计算机上,程序大部分工作,除了astr-> d的最后一个值,它打印出一些非常大的负数。所以我的问题是,为什么这会发生在他的电脑上,但我的工作正常?以下是有问题的代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
struct a_struct{
int a;
float b;
int c;
double d;
};
struct a_struct* astr;
astr = (struct a_struct*)malloc(sizeof(astr));
astr->a = 5;
astr->b = 5.55;
astr->c = 77;
astr->d = 888.8888;
printf("Value of a in astr is %d\n", astr->a);
printf("Value of b in astr is %f\n", astr->b);
printf("Value of c in astr is %d\n", astr->c);
printf("Value of d in astr is %lf\n", astr->d);
return 0;
}
答案 0 :(得分:10)
你至少有两个问题。
首先,您的malloc
来电不正确。
astr = (struct a_struct*)malloc(sizeof(astr));
astr
是一个指针,因此sizeof(astr)
是指针的大小。您希望分配足够的内存来保存struct astruct
类型的对象。
astr = (struct a_struct*)malloc(sizeof (struct a_struct)));
或者,更简单,更健壮:
astr = malloc(sizeof *astr);
(sizeof
的参数未被评估,因此sizeof *astr
会为您提供astr
指向的大小,而不会尝试取消引用它。由于{{1} {} }返回一个malloc
,它被隐式转换为所需的指针类型。)
其次,您使用格式错误打印void*
的格式不正确。 astr->d
格式适用于%f
和float
个参数(因为double
的{{1}}个参数会提升为float
)。 printf
参数的正确格式为double
。只需对long double
和%Lf
使用%f
即可。 (从C99开始astr->b
相当于astr->d
,但最好只使用"%lf"
。)
第三个(好的,我错误计算),您应该通过将结果与%f
进行比较来检查%f'
调用是否成功。对于如此小的分配,它不会可能失败,但这是一个非常好的习惯,可以持续检查。如果失败,您可以使用错误消息中止程序(对于较大的程序,可能会调用一些更复杂的错误处理)。
答案 1 :(得分:1)
这是因为程序错误地分配了内存。下面的语句实际上分配的内存等于指针的大小,可能是32位或64位,具体取决于操作系统架构。
struct a_struct* astr;
astr = (struct a_struct*)malloc(sizeof(astr));
相反,你应该这样做:
struct a_struct* astr;
astr = (struct a_struct*)malloc(sizeof(struct a_struct));
答案 2 :(得分:0)
如果您动态分配内存,则应注意为对象分配内存以保存数据,而不仅仅是指向您尚未分配的内容的第一个成员的指针。 &#34;反过来&#34;将结构显式声明为变量,然后指向其地址的指针:
struct a_struct astrV;
struct a_struct *astr = &astrV;