为什么这个程序在我的计算机上工作正常,但导致另一台计算机溢出?

时间:2016-05-29 20:10:14

标签: c pointers struct

我正在教朋友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;
}

3 个答案:

答案 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格式适用于%ffloat个参数(因为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;