当gcc -Wall
在没有警告的情况下编译时,我感到很惊讶。这真的是合法的C吗?编写这样的代码有什么风险?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a;
int b;
} MyStruct;
int main(void) {
MyStruct *s = malloc(sizeof(*s)); // as opposed to malloc(sizeof(MyStruct))
s->a = 5;
printf("%d\n", s->a);
}
答案 0 :(得分:5)
它不仅合法,而且更可取。这样您就可以让编译器推导出实际类型而不是手动执行它。
答案 1 :(得分:2)
sizeof
在编译时进行评估。在此上下文中,*s
解析为*s
的类型,它不会取消引用指针。
这是使用sizeof
的规范方式。如果您使用sizeof(int)
,那么如果类型发生更改(在这种情况下,可能不太可能,但仍然如此),则会留下错误的开头。
答案 2 :(得分:1)
书写
MyStruct *s = malloc(sizeof(*s));
与
具有完全相同的效果MyStruct *s = malloc(sizeof(MyStruct));
除了现在你只编写MyStruct 一次。也就是说,您分配的对象会自动确定其源类型,从而减少出错的可能性。
例如 - 它发生在我身上 - 你从MyStruct
开始。然后,您决定为不同目的还另外MyStruct
。因此,您最终会得到两种不同的结构:MyStruct
和AnotherStruct
。
然后,您重构代码并将一些变量从MyStruct
更改为AnotherStruct
,最后以
AnotherStruct *s = malloc(sizeof(MyStruct));
实际上可能在几种情况下,或者很长一段时间内,直到你再做一点,并且在那时,在任一结构中完全无关的改变。在 点,您的代码将变为kaboom。
E.g。
typedef struct {
int a;
int b;
} StructA;
typedef struct {
int a;
int b;
int c;
} StructB;
int main() {
// No problem here except wasted space
StructA *s = malloc(sizeof(StructB));
// t->c dwells in undefined country
StructB *t = malloc(sizeof(StructA));
}