它可能是安全的,但并不完全保证安全。
在大多数现代系统中,所有指针(至少所有对象指针)具有相同的表示形式,从一个指针类型转换为另一个只是重新解释构成表示的位。但C标准并不保证这一点。
char *p = malloc (sizeof (int));
这将给您一个指向sizeof(int)
字节数据的char*
指针(假设malloc()
成功)。
int *q = (int *)p;
这将char*
指针转换为int*
指针。由于int
比char
更大,因此int*
指针可能需要较少的信息来指示它所指向的内容。例如,在一个以字为单位的机器上,int*
可能只需指向一个字,而char*
必须包含一个字指针和一个指示它所指向的字节在该字中的偏移量。(我曾经在一个名为Cray T90的系统上工作过,它就是这样工作的。)因此,从char*
到int*
的转换实际上可能会丢失信息。
free (q);
由于
free()
接受一个
void*
类型的参数,因此参数
q
会从
int*
隐式转换为
void*
。在语言标准中没有保证将
char*
指针转换为
int*
,然后将结果转换为
void*
会得到与直接将
char*
转换为
void*
相同的结果。
另一方面,由于malloc()
总是返回一个指向任何类型的正确对齐的指针,即使在int*
和char*
具有不同表示的系统上,它也不太可能在这种特殊情况下引起问题。
因此,您的代码实际上肯定可以在您可能正在使用的任何系统上正确工作,并且即使在您可能从未见过的奇异系统上也非常非常可能正常工作。
尽管如此,我建议编写可以轻松证明为正确的代码,方法是保存原始指针值(类型为char*
)并将其传递给free()
。如果需要几段文本来证明您的代码几乎肯定是安全的,则简化您的假设可能会为您节省长期的精力。如果程序中出现其他问题(相信我,会出问题),则最好少担心一个可能的错误源。
您的代码存在更大的潜在问题是您没有检查malloc()
是否成功。如果您引用了分配的内存,则在它失败时您不会做任何失败的事情(转换和free()
调用可以使用null指针),但您可能会遇到麻烦。
更新:
您问您的代码是否合法;您没有问它是否是实现您正在做的最好方法。
malloc()
返回一个void*
结果,可以通过赋值隐式地转换为任何对象类型的指针。 free()
需要一个void*
参数;您传递给它的任何对象类型的指针参数都将被隐式转换为void*
。这个往返转换(void*
到something_else*
到void*
)是安全的。除非您进行某种类型的强行转换(将相同的数据块解释为两种不同的类型),否则无需进行任何转换。
而不是:
char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);
你可以直接编写:
int *p = malloc(sizeof *p);
...
free(p);
请注意在调用
malloc()
函数时,参数中使用了
sizeof *p
。这样可以不必显式地引用指针变量
p
的类型,而直接得到它所指向的对象的大小。这避免了意外使用错误类型的问题。
double *oops = malloc(sizeof (int))
编译器可能不会对此发出警告。
double *ptr = malloc(sizeof * ptr);…free(ptr);
是安全且最好的方法。除非您在做一些非常奇怪的事情,否则您不应该需要将指针与malloc()
和free()
一起使用进行强制转换; 隐式转换将恰好完成您所需的操作。 - Keith Thompsonvoid*
,并且可以用它来指向不同类型。但是在void*
与其他指针类型之间的转换并不需要强制类型转换;只需将值分配给指针变量即可进行隐式转换。 - Keith Thompson