C 使用未定义的指针分配内存
当C 使用未定义的指针分配内存,c,C,当gcc-Wall在没有任何警告的情况下编译这篇文章时,我感到惊讶。这真的合法吗?这样编写代码有什么风险 #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))
gcc-Wall
在没有任何警告的情况下编译这篇文章时,我感到惊讶。这真的合法吗?这样编写代码有什么风险
#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);
}
#包括
#包括
类型定义结构{
INTA;
int b;
}我的结构;
内部主(空){
MyStruct*s=malloc(sizeof(*s));//与malloc(sizeof(MyStruct))相反
s->a=5;
printf(“%d\n”,s->a);
}
它不仅是合法的,甚至比其他选择更可取。这样,编译器就可以推断出实际的类型,而不是手动操作。sizeof
在编译时进行计算。在此上下文中,*s
解析为*s
的类型,它不会取消对指针的引用
这是使用sizeof
的标准方法。如果使用了sizeof(int)
,则在类型更改时会留下一个错误的空白(在这种情况下,可能不太可能,但仍然如此)。
MyStruct *s = malloc(sizeof(*s));
具有完全相同的效果
MyStruct *s = malloc(sizeof(MyStruct));
只是现在你只写了一次我的短信。也就是说,您正在分配的对象的源类型是自动确定的,这减少了出错的机会
例如,这发生在我身上,你从一个MyStruct
开始。然后您决定您还需要一个不同的MyStruct
,用于不同的目的。因此,您将得到两种不同的结构,MyStruct
和AnotherStruct
然后重构代码,将一些变量从MyStruct
更改为AnotherStruct
,最后得到
AnotherStruct *s = malloc(sizeof(MyStruct));
这可能在几种情况下,或者在很长一段时间内有效,直到你在这两种结构中做了另一个小的、完全无关的改变。在这一点上,您的代码将发出咔嗒声
例如
建议这样做,以便显式强制转换。是的,它是有效的,并且是推荐的。@Antoh这不是关于强制转换@Deduplicator的结果可能的副本否,它不需要注意给定:
void function(const char*n){short a[atoi(n)];size_t s=sizeof(a)/sizeof(a[0]);使用a和s的代码。}
,sizeof(a)的值
是一个运行时计算,因为a
是一个可变长度数组。(请注意,sizeof(a[0])
仍然是一个编译时计算。)除了这个狭隘的教学目的之外,我对代码的质量没有任何要求(这很糟糕)。@JonathanLeffler:没错,VLA的是个例外。
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));
}