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