将malloc的结果转换为char(而不是char*)-为什么';你不抱怨吗?

将malloc的结果转换为char(而不是char*)-为什么';你不抱怨吗?,c,casting,C,Casting,这两条线有什么区别 我的理解是,第二行是错误的,但出于某种原因,编译器什么也没说。第二行是错误的(强制转换为char会将指针截断到一个字节,使数据tmpString包含无效地址),但是C中的所有类型转换都是未经检查的,因此您永远不会在它们上面得到错误。是的,第二行有未定义的行为。由于案例是显式的,编译器只是假设您知道自己在做什么。本质上,第二个强制转换将指针值的第一个字节解释为字符代码。最后一句只是说明性的——你甚至不能完全相信会发生什么。第一行将malloc返回的(void)指针转换为指向ch

这两条线有什么区别


我的理解是,第二行是错误的,但出于某种原因,编译器什么也没说。

第二行是错误的(强制转换为
char
会将指针截断到一个字节,使数据
tmpString
包含无效地址),但是C中的所有类型转换都是未经检查的,因此您永远不会在它们上面得到错误。

是的,第二行有未定义的行为。由于案例是显式的,编译器只是假设您知道自己在做什么。本质上,第二个强制转换将指针值的第一个字节解释为字符代码。最后一句只是说明性的——你甚至不能完全相信会发生什么。

第一行将malloc返回的(void)指针转换为指向char的指针,从而保留了它的指针性。它告诉编译器的只是“X位置的内存应该被视为一个字符数组”

第二个强制转换将malloc返回的指针转换为单个字符。这是不好的,原因有很多:

  • 你失去了指针,因为你刚刚把指针变成了完全不同的东西
  • 由于字符的大小远小于指针的大小(在许多情况下,指针的大小为32或64位,但字符仅为8位),并且“多余”位将被丢弃,因此指针的大部分数值也将丢失

我认为警告级别足够高的编译器应该警告第二个赋值。

假设
tmpString
具有类型
char*
,那么第二行应该是违反约束的,至少在以下条件下:

6.5.16.1简单赋值 约束条件

1以下其中一项应适用:112) -左操作数具有原子、限定或非限定算术类型,右操作数具有 算术类型

-左操作数具有结构或并集的原子、限定或非限定版本 与权利类型兼容的类型

-左操作数具有原子、限定或非限定指针类型,以及 左值转换后左操作数的类型)两个操作数都是 指向兼容类型的合格或不合格版本的指针,以及指向的类型 左边的to具有右边所指类型的所有限定符

-左操作数具有原子、限定或非限定指针类型,以及 左值转换后左操作数的类型(一个操作数是指针) 指向一个对象类型,另一个是指向 void,左侧所指的类型具有所指类型的所有限定符 凭权利

-左操作数是原子指针、限定指针或非限定指针,右操作数是空指针 指针常数;或

-左操作数的类型为原子、限定或非限定布尔,右操作数的类型为 指针。
还是我遗漏了什么?

您不需要在C程序中强制转换
malloc
的返回值。而
sizeof(char)
1
。如果你清除了这些内容,你的代码看起来就简单多了,你就不会遇到这样的问题。启用警告。都是。编译器会抱怨的。有许多领域(IMHO),C还不够禁止。。但如果是这样,某人(某处)会感到不安:D@CarlNorum这个结论和这个问题有什么关系?我不确定我是否明白你的意思。添加额外的(不必要的)强制转换,然后抱怨编译器做了什么或没有做什么,似乎是为了抱怨而抱怨@pst的想法是对的。@CarlNorum 1。删除
sizeof(char)
与铸造和问题无关。2.需要强制转换malloc的结果也不相关。如果有一个表达式代替
malloc
,例如
tmpString=(char)p,那么问题的本质不会改变//p是空的*
@Carl Norum。我回滚了您的编辑,因为它取决于endianness@ArmenTsirunyan不,这不取决于endianness——这是我在编辑中的观点。你的答案是“第一个字节”,这只适用于一个小的endian系统。转换为
char
将产生最低有效字节,而不管其是否为endianness。是的,在第二种情况下,应该有一条警告,即“赋值从整数生成指针而不转换”。不,因为存在转换。我认为这个例子是一个很好的论点,认为强制转换是有害的,应该被视为代码气味。@R。事实上,对于这种情况,
clang
说:
警告:不兼容的整数到指针转换从“char”分配给“char*”
。GCC告诉我有关强制转换的信息:
警告:从指针强制转换为不同大小的整数
,以及关于赋值的信息:
警告:赋值使指针从整数转换为不带强制转换的整数
。在第二种情况下,如果编译器使用C99或警告的音量足够大,那么对
tmpString
的赋值应该会导致警告。类似于“赋值从整数生成指针而不强制转换”。也就是说,假设
tmpString
是人们所期望的
char*
。标准规定,任何指针类型都可以转换为任何整数类型,反之亦然。因此,
char
将隐式转换为兼容的指针类型。(6.3.2.3)@teppic:强制转换是合法的,但赋值是不合法的。“考虑左值转换后左操作数将具有的类型”部分使其正常——左值转换意味着右操作数
tmpString = (char*)malloc((strlen(name) + 1) * sizeof(char));
tmpString = (char )malloc((strlen(name) + 1) * sizeof(char));