我要投malloc的结果吗?

我要投malloc的结果吗?,c,malloc,casting,C,Malloc,Casting,在中,有人在一篇文章中建议,我应该而不是malloc的结果。i、 例如,我应该这样做: int *sieve = malloc(sizeof(int) * length); 而不是: int *sieve = (int *) malloc(sizeof(int) * length); 为什么会出现这种情况?在C中,您会得到从void*到任何其他(数据)指针的隐式转换。在C中,您不需要强制转换malloc的返回值。malloc返回的指向void的指针自动转换为正确的类型。但是,如果希望代码用C

在中,有人在一篇文章中建议,我应该而不是
malloc
的结果。i、 例如,我应该这样做:

int *sieve = malloc(sizeof(int) * length);
而不是:

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

为什么会出现这种情况?

在C中,您会得到从
void*
到任何其他(数据)指针的隐式转换。

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

int *sieve = malloc(sizeof *sieve * length);
另外,如果您更改了
筛的类型,则无需担心更改表达式的右侧

正如人们指出的那样,演员阵容很糟糕。尤其是指针投射

TL;博士 有两个问题。强制转换和您正在使用类型而不是变量作为sizeof的参数。相反,要这样做:

int *sieve = malloc(sizeof *sieve * length);
长版本 ;您不投结果,因为:

  • 这是不必要的,因为在这种情况下,
    void*
    会自动安全地升级为任何其他指针类型
  • 它会给代码增加混乱,强制转换不容易读取(特别是指针类型很长时)
  • 它让你重复你自己,这通常是不好的
  • 如果您忘记包含
    ,它可能会隐藏错误。这可能会导致崩溃(或者更糟糕的是,直到稍后在代码的某个完全不同的部分才会导致崩溃)。考虑指针和整数大小不同会发生什么情况;然后,您通过强制执行来隐藏警告,可能会丢失您返回的地址中的一些内容。注意:从C99开始,隐式函数不再使用C,这一点不再相关,因为没有自动假设未声明的函数返回
    int
作为澄清,请注意我说的是“你不投”,而不是“你不需要投”。在我看来,即使你做对了,也不能包括演员。这样做没有任何好处,但是一系列潜在的风险,包括演员阵容,表明你不知道这些风险

正如注释者指出的,上面提到的是直C,而不是C++。我非常相信C和C++是独立的语言。 为了进一步添加,代码不必要地重复类型信息(
int
),这可能会导致错误。最好取消引用用于存储返回值的指针,将两者“锁定”在一起:

int *sieve = malloc(length * sizeof *sieve);
这也会将
长度
移到前面以增加可见性,并删除带有
sizeof
的多余括号;只有当参数是类型名时才需要它们。许多人似乎不知道(或忽略)这一点,这使得他们的代码更加冗长。请记住:
sizeof
不是一个函数!:)


在某些罕见的情况下,向前移动
length
可能会增加可见性,但还应注意,在一般情况下,最好将表达式写成:

int *sieve = malloc(sizeof *sieve * length);
由于首先保持
sizeof
,因此在这种情况下,可以确保至少使用
size\t
数学进行乘法


比较:
malloc(sizeof*sieve*length*width)
vs.
malloc(length*width*sizeof*sieve)
如果
宽度
长度
的类型比
大小
小,则第二个可能会溢出
长度*宽度
,在C中,您可以隐式地将
无效
指针转换为任何其他类型的指针,因此不需要强制转换。使用一个可以向偶然的观察者提出为什么需要一个原因,这可能是误导的。

正如其他陈述的那样,C是不需要的,但是C++是必需的。如果你认为你将用C++编译器编译你的C代码,不管什么原因,你可以使用宏,比如:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif
这样,您仍然可以以非常紧凑的方式编写:

int *sieve = NEW(int, 1);

< > >,它将编译为C和C++。< /P> < P>不强制强制转换<代码> MalOC><代码>的结果,因为它返回了代码> Value*/Cuff>,并且<代码>空白> /COD>可以指向任何数据类型。p> 你投了,因为:

    <> LI>使C代码和C++之间的代码“更强”>更便携< /强>,因此经验表明,很多程序员声称他们在C++中真正编写C(或者C加上本地编译器扩展)时正在编写。
  • 如果不这样做可能会隐藏错误:请注意,当编写
    类型*
    类型**
    时,所有的例子都会让人感到困惑
  • 它让你注意不到你没有
    #包含
    一个合适的头文件,这会错过树的森林。这与说“不要担心你没有让编译器抱怨没有看到原型——讨厌的stdlib.h才是真正需要记住的重要东西!”
  • 它强制进行额外的认知交叉检查。它将(声称的)所需类型放在您对该变量的原始大小所做的算术旁边。我打赌你可以做一个SO研究,表明当有演员阵容时,
    malloc()。与断言一样,揭示意图的注释可以减少bug
    
  • 以机器可以检查的方式重复你自己通常是一个很好的想法。事实上,这就是断言,而cast的使用就是断言。断言仍然是我们获得代码正确性的最常用的技术,因为图灵多年前就提出了这个想法

返回的类型为void*,可以将其强制转换为所需类型的数据指针,以便取消引用。

现在不需要强制转换由
malloc()
返回的值,但我想添加一个似乎不需要的点
int *sieve = NEW(int, 1);
auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)
NEW_ARRAY(sieve, length);
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}
double d;
void *p = &d;
int *q = p;
/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif
-Wold-style-cast (C++ and Objective-C++ only) Warn if an old-style (C-style) cast to a non-void type is used within a C++ program. The new-style casts (dynamic_cast, static_cast, reinterpret_cast, and const_cast) are less vulnerable to unintended effects and much easier to search for.
long x = 5;
double *p = (double *)&x;
double y = *p;
struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;
int x = 5;
printf("%p\n", (void *)&x);