对于下面的C代码,比较int指针a和b的定义;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a=malloc(sizeof(int));
int *b=(int *)malloc(sizeof(int));
return(0);
}
以任何方式更好地对malloc函数返回的void类型的指针进行类型转换? 或者在分配到左侧的int指针时是自动类型化的吗? 在哪种情况下,如果有的话,它是否可以证明是必要的而不仅仅是强制性的?
请说明右侧的类型转换为左侧类型的隐式类型转换是否适用于此。
答案 0 :(得分:16)
C语言不需要强制转换,但是对于C ++兼容性,您可能需要强制转换。这是C不是C ++子集的地方之一。
以下内容将在C中编译,但不能在C ++中编译:
int *a=malloc(sizeof(int));
以下将在C和C ++中编译:
int *b=(int *)malloc(sizeof(int));
答案 1 :(得分:12)
void
,因此malloc()
返回了char *
。现在,你需要做演员表。因此,铸造malloc()
的设计模式开发并影响了编写下一组代码的所有人,并且人们仍然在阅读这些代码主体,并将模式向前推进。但是C89无效,所以是时候简化代码了。答案 2 :(得分:9)
简单地说:
如果你已经包含了stdlib.h
,那么演员阵容绝对没有,应该被删除。毕竟,您已经指定了类型。
如果你还没有,则演员将掩盖错误,这是不好的。
永远不要在C代码中使用该强制转换。
在C ++中,强制转换是必要的,因为C ++不允许void *
和其他指针类型之间的隐式转换。另一方面,在C ++中,使用的内容比malloc()
更好,例如new
或容器类。
编写将在其中编译的代码毫无意义。你应该总是知道你正在写什么语言,并且在子集中写作会强迫你使用一种在任何一种语言中都较差的结构。我熟悉的C ++编译器也将编译C代码,C ++中有明确的规定可以轻松地与C代码链接。如果你把它编译为C ++,错误信息(没有强制转换)将指出你的错误。
所有演员都会做的是掩盖可以在别处咬你的错误。它不会做任何有用的事情。不要这样做。
答案 3 :(得分:8)
在C中,演员阵容是不必要的。 malloc
返回void*
,C标准声明:
指向void的指针可以转换为 或指向任何不完整或 对象类型。指向任何指针 不完整或对象类型可能 转换为指向void和的指针 再次回来;结果应该比较 等于原始指针。
此外,K&amp; R2说:
任何指向对象的指针都可以转换为void *类型而不会丢失 信息。如果结果是 转换回原始指针 类型,原始指针是 恢复。不像 指向指针的转换 在Par.A.6.6中讨论过, 通常需要一个明确的演员, 指针可以分配给和从 void *的类型指针,可能是 与他们相比。
关于C ++兼容性可能有一点,因为在C ++中,强制转换是强制性的。但是,恕我直言,这几乎不相关,因为惯用的C ++无论如何都要求使用new
而不是malloc
。
答案 4 :(得分:4)
转换malloc()
的返回值是一个C ++习语,在C代码中没有位置。只有当你想用C ++编译代码时才有必要,你不应该这样做,因为C和C ++是具有不同语义的不同语言。
只有你想创建一个C库来定义头文件中的内联函数才能从C ++中使用它才有意义。随着链接时优化的出现,这种希望不再是必要的,因为即使在不同的源文件中定义函数也可以内联。
对于声称显式强制转换增加可读性的人,请考虑给定的示例
int *b=(int *)malloc(sizeof(int));
如何完全重复三种类型的可读性比
更具可读性int *b = malloc(sizeof *b);
超出我的范围。
C ++ 0x甚至添加了类型推断以消除类似的重复,所以我并不认为这是有争议的。
答案 5 :(得分:3)
如果我们正在谈论C,最佳做法是不投射malloc()
的结果。如果我们正在谈论C ++,最佳做法是使用new
而不是malloc()
1 。
我建议不要强制转换结果的原因是,如果忘记#include
stdlib.h,或者在范围内没有malloc()
的原型,则应避免出现问题。直到C99,如果你有一个没有事先声明的函数调用,编译器会隐式键入函数调用以返回int
。如果没有强制转换,这将导致不兼容的分配警告。使用强制转换,警告被抑制,并且可能会导致运行时错误,因为从malloc()
返回的值将从指针转换为int并再次返回指针,这不能保证有意义。
malloc()
转换为new
。答案 6 :(得分:1)
以任何方式更好地对malloc函数返回的void类型的指针进行类型转换?
是。它的含义更清晰。这和我写的原因相同
a = b + (c * d);
现在,由于算术运算符的优先级规则,我知道这里不需要“()”,但是它们帮助我(和其他人)清楚地看到了我的意图。
$ .02,等等:))
-k