在这个问题上,有人在评论中建议我不要使用malloc的结果。即,我应该这样做:
int *sieve = malloc(sizeof(*sieve) * length);
而不是:
int *sieve = (int *) malloc(sizeof(*sieve) * length);
为什么会这样?
在这个问题上,有人在评论中建议我不要使用malloc的结果。即,我应该这样做:
int *sieve = malloc(sizeof(*sieve) * length);
而不是:
int *sieve = (int *) malloc(sizeof(*sieve) * length);
为什么会这样?
当前回答
我更喜欢演演员,但不是手动。我最喜欢使用glib中的g_new和g_new0宏。如果不使用glib,我会添加类似的宏。这些宏在不损害类型安全的情况下减少代码重复。如果类型错误,将在非空指针之间进行隐式转换,这将导致警告(C++中的错误)。如果忘记包含定义g_new和g_new0的标头,则会出现错误。gnew和gnew0都采用相同的参数,不像malloc采用比calloc更少的参数。只需添加0即可获得零初始化内存。该代码可以用C++编译器编译而无需更改。
其他回答
malloc的主要问题是获得正确的大小。
malloc()返回的内存是非类型的,由于简单的强制转换,它不会神奇地获得有效的类型。
我想这两种方法都很好,选择应该取决于程序员的意图。
如果为类型分配内存,则使用强制转换。
ptr=(T*)malloc(sizeof(T));
如果为给定指针分配内存,则不要使用强制转换。
ptr=malloc(sizeof*ptr);
Ad 1
第一种方法通过为给定类型分配内存,然后将其强制转换以确保分配给正确的指针,从而确保正确的大小。如果使用了不正确的ptr类型,则编译器将发出警告/错误。如果ptr的类型被更改,那么编译器将指出代码需要重构的地方。
此外,第一种方法可以组合成类似于C++中新运算符的宏。
#define NEW(T) ((T*)malloc(sizeof(T)))
...
ptr = NEW(T);
此外,如果ptr为void*,则此方法有效。
Ad 2
第二个方法不关心类型,它通过从指针的类型中获取数据来确保正确的大小。这种方法的主要优点是,每当ptr的类型发生变化时,都可以自动调整存储大小。它可以在重构时节省一些时间(或错误)。
缺点是,如果ptr为空,则该方法不起作用,但它可能被认为是一件好事。而且它不适用于C++,因此不应在C++程序将要使用的头中的内联函数中使用。
就我个人而言,我更喜欢第二种选择。
malloc的转换在C中是不必要的,但在C++中是必需的。
C中不需要铸造,因为:
在C的情况下,void*会自动安全地升级为任何其他指针类型。如果您忘记包含<stdlib.h>,它可能会隐藏错误。这可能会导致崩溃。如果指针和整数的大小不同,则通过强制转换隐藏警告,可能会丢失返回地址的位。如果指针的类型在声明时发生了更改,那么可能还需要更改调用和强制转换malloc的所有行。
另一方面,强制转换可能会增加程序的可移植性。即它允许C程序或函数编译为C++。
void指针是一个通用对象指针,C支持从void指针类型到其他类型的隐式转换,因此不需要显式类型转换。
然而,如果您希望相同的代码在不支持隐式转换的C++平台上完美兼容,则需要进行类型转换,因此这一切都取决于可用性。
返回的类型为void*,可以将其转换为所需类型的数据指针,以便可以取消引用。
来自维基百科:
铸造的优点包括强制转换可以允许C程序或函数编译为C++。强制转换允许最初返回char*的1989年以前版本的malloc。如果目标指针类型发生变化,强制转换可以帮助开发人员识别类型大小的不一致,特别是如果指针声明的位置远离malloc()调用(尽管现代编译器和静态分析器可以在不需要强制转换的情况下警告此类行为)。铸造的缺点根据ANSI C标准,铸件是多余的。添加强制转换可能会掩盖将标头stdlib.h包含在找到了malloc的原型。如果没有malloc的原型,标准要求C编译器假设malloc返回一个int。如果没有强制转换,则警告为当该整数被分配给指针时发出;然而,随着演员,这个警告没有产生,隐藏了一个bug。在某些情况下体系结构和数据模型(例如64位系统上的LP64,其中long和指针为64位,int为32位),此错误可能实际上导致未定义的行为,正如隐式声明的malloc返回32位值,而实际定义的函数返回64位值。取决于调用约定和内存布局,这可能会导致堆栈损坏。这个问题不太可能在现代编译器中不被注意,因为它们统一地生成警告已使用未声明的函数,因此警告将仍然出现。例如,GCC的默认行为是显示警告:“内置的不兼容隐式声明函数”,而不管是否存在强制转换。如果指针的类型在其声明时发生了更改,则可以此外,需要更改调用和强制转换malloc的所有行。
尽管malloc不带强制转换是首选方法,大多数有经验的程序员都会选择它,但在意识到问题后,您应该使用任何您喜欢的方法。
即:如果您需要将C程序编译为C++(尽管它是一种单独的语言),则必须强制转换使用malloc的结果。