C++ C语言中不必要的指针强制转换
我在这个帖子上得到了对我答案的评论: 简而言之,我有这样的代码:C++ C语言中不必要的指针强制转换,c++,c,pointers,C++,C,Pointers,我在这个帖子上得到了对我答案的评论: 简而言之,我有这样的代码: int * somefunc (void) { int * temp = (int*) malloc (sizeof (int)); temp[0] = 0; return temp; } 我得到这样的评论: 我能不能说,请不要投 malloc的返回值?事实并非如此 必需,并且可以隐藏错误 我同意C++中不需要强制转换。C++中强制转换,所以我通常添加它们,以防有一天我必须在C++中输入代码。 然而,我想知道这样的
int * somefunc (void)
{
int * temp = (int*) malloc (sizeof (int));
temp[0] = 0;
return temp;
}
我得到这样的评论:
我能不能说,请不要投
malloc的返回值?事实并非如此
必需,并且可以隐藏错误
<>我同意C++中不需要强制转换。C++中强制转换,所以我通常添加它们,以防有一天我必须在C++中输入代码。
然而,我想知道这样的强制转换如何隐藏错误。有什么想法吗
编辑:
似乎双方都有非常好和有效的论点。谢谢大家发帖。铸造一个返回(void*)而不是(int*)的函数是无害的:您铸造的是一种指向另一种类型的指针
将返回整数的函数转换为指针很可能是不正确的。如果您没有显式地强制转换它,编译器会标记它。似乎很适合我发布一个答案,因为我留下了注释:p 基本上,如果忘记包含
stdlib.h
,编译器将假定malloc
返回int
。没有施法,你会得到警告。有了演员你就不会了
因此,通过施放,你将一无所获,并冒着压制合法警告的风险
关于这方面的文章很多,快速的谷歌搜索会找到更详细的解释
编辑
有人认为
TYPE * p;
p = (TYPE *)malloc(n*sizeof(TYPE));
当您意外地没有分配足够的内存时,这一点很明显,比如说,您认为p
是TYPe
而不是TYPe
,因此我们应该使用malloc,因为这种方法的优点覆盖了意外抑制编译器警告的较小成本
我想指出两点:
p=malloc(sizeof(*p)*n)
始终确保分配正确的空间量p
的类型,您需要在3个位置进行更改:一次在声明中,一次在malloc
中,一次在cast中int *temp = (int *)malloc(sizeof(double));
在某些情况下,您可能希望这样做,但我怀疑这种情况很少见。嗯,我认为恰恰相反——总是直接将其转换为所需的类型 > P>另一方面,如果你需要将代码移植到C++,最好使用“新”操作符。
实际上,一个演员可以隐藏错误的唯一方法是,如果你从一个数据类型转换为更小的数据类型和丢失的数据,或者如果你把梨转换成苹果。以以下为例:
int int_array[10];
/* initialize array */
int *p = &(int_array[3]);
short *sp = (short *)p;
short my_val = *sp;
在这种情况下,转换为short将从int中删除一些数据。在这种情况下:
struct {
/* something */
} my_struct[100];
int my_int_array[100];
/* initialize array */
struct my_struct *p = &(my_int_array[99]);
在这种情况下,您最终会指向错误类型的数据,甚至指向无效内存
但总的来说,如果你知道自己在做什么,就可以做演员。当您从malloc获取内存时更是如此,它恰好返回一个空指针,除非您强制转换它,否则您根本无法使用它,并且如果您强制转换到左值(赋值左侧的值)无论如何都无法接受的对象,大多数编译器会警告您。我认为您应该将强制转换放入。考虑类型有三个位置:
T1 *p;
p = (T2*) malloc(sizeof(T3));
这两行代码之间可能有很大的距离。因此,编译器最好将T1==T2。直观地验证T2==T3更容易
如果你错过了T2的演员阵容,那么你必须希望T1==T3
另一方面,您缺少stdlib.h参数,但我认为这不太可能是一个问题。它可能引入的一个错误是,如果您在64位系统上使用C(而不是C++)进行编译 基本上,如果忘记包含stdlib.h,将应用默认的int规则。因此,编译器将愉快地假设
malloc
具有int malloc()的原型
在许多64位系统上,int为32位,指针为64位
哦,值被截断了,你只得到指针的32位!现在,如果您强制转换返回值malloc
,此错误将被强制转换隐藏。但如果不这样做,您将得到一个错误(性质为“无法将int转换为t*”)
<>这当然不适用于C++,原因有2。首先,它没有默认的int规则,其次它需要强制转换
总之,你应该只在C++代码中新的:P.
这个问题被标记为C和C++,所以它至少有两个答案,imHo:< /P> C 啊哼。。。你想干什么就干什么 我相信上面给出的理由“如果你不包括“stdlib”,那么你就不会得到警告”是无效的,因为人们不应该依靠这种黑客来避免忘记包括一个标题 使您不能编写强制转换的真正原因是C编译器已经悄悄地将void*
强制转换为您想要的任何指针类型,因此,自己这样做是多余和无用的
如果您想拥有类型安全性,您可以切换到C++或编写自己的包装函数,例如:
int * malloc_Int(size_t p_iSize) /* number of ints wanted */
{
return malloc(sizeof(int) * p_iSize) ;
}
C++
有时,即使在C++中,你也必须从MalC/ReAlcC/FULL UTILS中获利。那你就得投了。但你已经知道了。和往常一样,使用static_cast()比使用C样式的cast更好
在C中,您可以通过模板覆盖malloc(和realloc等)以实现类型安全:
template <typename T>
T * myMalloc(const size_t p_iSize)
{
return static_cast<T *>(malloc(sizeof(T) * p_iSize)) ;
}
模板
T*myMalloc(常数大小)
{
返回静态(malloc(sizeof(T)*p_iSize));
}
其使用方式如下:
int * p = myMalloc<int>(25) ;
free(p) ;
MyStruct * p2 = myMalloc<MyStruct>(12) ;
free(p2) ;
int*p=myMalloc(25);
自由基(p);
MyStruct*p2=myMalloc(12);
自由(p2);
下面呢
// error: cannot convert ‘int*’ to ‘short int*’ in initialization
short * p = myMalloc<int>(25) ;
free(p) ;
#if CPLUSPLUS
#define MALLOC_CAST(T) (T)
#else
#define MALLOC_CAST(T)
#endif
...
int * p;
p = MALLOC_CAST(int *) malloc(sizeof(int) * n);
#if CPLUSPLUS
#define MYMALLOC(T, N) static_cast<T*>(malloc(sizeof(T) * N))
#else
#define MYMALLOC(T, N) malloc(sizeof(T) * N)
#endif
...
int * p;
p = MYMALLOC(int, n);
int from_f(float f)
{
return *(int *)&f;
}
int *p = (int *)malloc(sizeof(int) * 10);