自动为C结构分配内存



我一直在打开和关闭C/C ,但是今天我在某本书中看到了我从未见过的东西:

struct item {
   int code;
   float prize;
};
void main() {
   struct item a,*b;
   a.code = 123;
   a.prize = 150.75;
   printf ("Code: %d, Prize %d", a.code, a.prize);
   b->code = 124;
   b->prize = 200.75;
   printf ("Code: %d, Prize %d", a->code, a->prize);
}

上面的值是正常的值,这是*b部分的惊喜。由于B是指指针,因此分配的内存应在堆栈上,大小为size_t(ex。64位),而其数据应仅通过在堆上分别分配来获得:

b = (item*)malloc(sizeof(struct item));

显然,不需要该。这怎么可能?

在您的情况下,b->codeb->prize正在访问非初始化的内存,结果是未定义的行为。不要这样做

要详细说明,没有

魔术 自动内存分配,使这些指针指向任何有效的内存。仅仅因为c 允许您编写一个代码,该代码访问非初始化的指针并不要求它是有效代码。您必须在您可以访问(从或写入)之前,将指针指向某些有效的内存位置。

任何不错的编译器都可能(不需要)发出针对这样的代码的警告。对于gcc,启用-Wuninitialized(添加-Wall启用)应显示

的警告

警告:" b"在此功能[ - wuninitializatized]

中使用

也就是说,您有另一个主要问题。您将float作为 %d格式指定符参数,再次调用UB。

 printf ("Code: %d, Prize %d", a.code, a.prize);
                         ^^^           ^^^^^^^^

相关,引用 C11,第§7.21.6.1

[...]如果有任何参数 不是相应转换规范的正确类型,行为是 未定义。

您应该使用%f打印float

最后,对于托管环境,main()的签名至少应为int main(void),以符合标准。

正如您正确诊断的那样,b是一个非初始化的指针。访问成员以读取和写作调用不确定的行为,没有内存是自动分配的,以指向非直接的指针。非初始化的指针只有不应该使用的不确定值。

在您的情况下,该程序似乎表现通常通常,但这只是一个巧合,并且在现代系统上不太可能:如果b恰好具有指向某些可访问内存的值,则因此,不会发生分割故障,但是谁知道修改了哪些对象以及这可能会产生什么进一步的后果...

不要执行此操作,并在当前编译器能够检测到此类错误时启用了更多警告:gcc -Wall -Wextraclang -Weverything

您的代码中还有其他几个问题:

  • 您不包括标准标题<stdio.h>;
  • 您通过printf格式%d;
  • 通过float
  • 您将main定义为返回void,它应该返回int;
  • 您不会使用newline结束输出到stdout

第二项还调用了未定义的行为。其他3通常没有可怕的后果,但仍应纠正。

这是一个更正的版本:

#include <stdio.h>
#include <stdlib.h>
struct item {
   int code;
   float prize;
};
int main(void) {
    struct item a, *b;
    a.code = 123;
    a.prize = 150.75;
    printf("Code: %d, Prize %fn", a.code, a.prize);
    b = malloc(sizeof(*b));
    if (b != NULL) {
        b->code = 124;
        b->prize = 200.75;
        printf ("Code: %d, Prize %fn", b->code, b->prize);
    }
    return 0;
}

相关内容

  • 没有找到相关文章

最新更新