我一直在使用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);
}
Run Code Online (Sandbox Code Playgroud)
以上打印值正常,这是一个令人惊讶的*b部分.由于b是一个指针,为它分配的内存应该在堆栈上,大小为size_t(例如64位),而其数据只能通过在堆上单独分配来获得:
b = (item*)malloc(sizeof(struct item));
Run Code Online (Sandbox Code Playgroud)
显然,没有必要这样做.这怎么可能?
在您的情况下,b->code并且b->prize正在访问未初始化的内存,结果是未定义的行为.不要那样做.
详细说明,没有 神奇发生自动内存分配,使这些指针指向任何有效的内存.只是因为C 允许你编写一个访问未初始化指针的代码并不强制它是一个有效的代码.你必须让指针指向一些有效的内存位置,然后才能访问(读取或写入)他们.
任何体面的编译器都可能(虽然不要求)对这样的代码产生警告.对于gcc,启用-Wuninitialized(通过添加启用-Wall)应显示类似的警告
警告:'b'在此函数中未初始化使用[-Wuninitialized]
也就是说,你有另一个主要问题.您正在传递一个floatas %dformat specifier参数,它再次调用它自己的UB.
printf ("Code: %d, Prize %d", a.code, a.prize);
^^^ ^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
相关的,引用C11,章节§7.21.6.1
[...]如果任何参数不是相应转换规范的正确类型,则行为未定义.
你应该%f用来打印float.
最后,对于托管环境,签名main()应该是int main(void),至少,以符合标准.