在这个问题上,有人在评论中建议我不要使用malloc的结果。即,我应该这样做:

int *sieve = malloc(sizeof(*sieve) * length);

而不是:

int *sieve = (int *) malloc(sizeof(*sieve) * length);

为什么会这样?


当前回答

在C语言中,不需要强制转换malloc的返回值。malloc返回的指向void的指针会自动转换为正确的类型。但是,如果您想用C++编译器编译代码,则需要强制转换。社区中的首选替代方案是使用以下方法:

int *sieve = malloc(sizeof *sieve * length);

另外,如果你改变了筛子的类型,你就不用担心改变表达式的右边。

正如人们所指出的那样,铸件是不好的。尤其是指针强制转换。

其他回答

在C语言中,可以隐式将void指针转换为任何其他类型的指针,因此不需要强制转换。使用一个可能会向不经意的观察者暗示需要一个的原因,这可能会误导人。

对我来说,这里的结论是,在C语言中使用malloc是完全没有必要的,但是如果你使用了C语言,它不会影响malloc,因为malloc仍然会为你分配你请求的内存空间。另一个原因是人们进行选角的原因或原因之一,这是为了使他们能够用C或C++编译相同的程序。

可能还有其他原因,但几乎可以肯定的是,其他原因迟早会让你陷入严重的麻烦。

来自维基百科:

铸造的优点包括强制转换可以允许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的结果。

正如其他人所说的,它不是C所必需的,而是C++所必需的。如果您认为要使用C++编译器编译C代码,无论出于何种原因,都可以使用宏,例如:

#ifdef __cplusplus
# define MALLOC(type) ((type *)malloc(sizeof(type)))
# define CALLOC(count, type) ((type *)calloc(count, sizeof(type)))
#else
# define MALLOC(type) (malloc(sizeof(type)))
# define CALLOC(count, type) (calloc(count, sizeof(type)))
#endif
# define FREE(pointer) free(pointer)

这样,您仍然可以以非常紧凑的方式编写它:

int *sieve = MALLOC(int); // allocate single int => compare to stack int sieve = ???;
int *sieve_arr = CALLOC(4, int); // allocate 4 times size of int => compare to stack (int sieve_arr[4] = {0, 0, 0, 0};
// do something with the ptr or the value
FREE(sieve);
FREE(sieve_arr);

它将为C和C++编译。

加上我学习计算机工程的经验,我发现我见过的两三位教授总是用C语言写作,但我问的那位教授(有着丰富的简历和对C语言的理解)告诉我,这是绝对没有必要的,但只用于绝对具体,并让学生们养成绝对具体的心态。从本质上讲,强制转换不会改变它的工作方式,它完全按照它所说的做,分配内存,强制转换不影响它,你会得到相同的内存,即使你错误地将它强制转换为其他东西(并以某种方式规避编译器错误),C也会以同样的方式访问它。

编辑:铸造有一定的意义。当您使用数组表示法时,生成的代码必须知道要到达下一个元素的开头,需要前进多少个内存位置,这是通过强制转换实现的。通过这种方式,您可以知道,对于double,您可以提前8个字节,而对于int,则可以提前4个字节,依此类推。因此,如果您使用指针表示法,则不会产生任何影响,在数组表示法中,这是必要的。