从char*转换为signed char*

10

我看到一段有效的C代码,尝试将其编译为C++,但出现了一个我无法理解的错误。

char* t;
signed char* v = t;

错误:从 char* 转换为 signed char* 是无效的。
根据我的了解,char 和 signed char 在语义上是相同的,但编译器仍认为它们是不同的类型。
我知道这个错误是由这两种类型之间的差异造成的,我的问题是:为什么存在这种差异?
据我所知,char 可以实现为 signed char 或 unsigned char 中的一种,因此应该与其中的一个完全相同。
我查阅了这个问题,但这个答案并没有回答我想知道的点。

1
我喜欢将signedunsigned char视为算术类型,基本上只是小整数,而char则是I/O类型--命令行参数、环境以及通过文件的读写都是以字符为单位进行的。 - Kerrek SB
1
这个问题已经在https://dev59.com/JnRC5IYBdhLWcg3wAcbU得到了解答。最基本的解释是,`unsigned char的范围是0..255,而signed char的范围是-127..128。所以你不能将一个值为-42的signed char转换为unsigned char,也不能将一个值为142的unsigned char转换为signed char。通常情况下,char被读作signed char`。 - alle_meije
@alle_meije 和 signed char 以及 char* 是相等的。虽然我搜索了,但我没有看到这个问题... - Geoffroy
这不是我读到的 char 对象能否保存负值是实现定义行为。 - alle_meije
我的意思是,“应该是这样还是那样”意味着你的代码将在一个编译器系统上工作,但可能在另一个上不起作用。这里的“实现”是指编译器的实现,你的代码不应该依赖于它。这与将指针NULL实现为数字0相同。大多数编译器都这样做,但不能保证。 - alle_meije
显示剩余2条评论
3个回答

11

实际上,我最终找到了与此相关的规范部分:

3.9.1 基本类型

  1. 声明为字符(char)的对象应足够大,以存储实现基本字符集中的任何成员。如果将该集合中的字符存储在字符对象中,则该字符对象的整数值等于该字符的单个字符文字形式的值。是否可以使用char对象保存负值是由实现定义的。字符可以明确地声明为无符号或有符号。普通的char、signed char和unsigned char是三种不同的类型。一个char、一个signed char和一个unsigned char占用相同的存储空间并具有相同的对齐要求(3.11);也就是说它们具有相同的对象表示形式。对于字符类型,对象表示的所有位都参与值表示。对于无符号字符类型,值表示的所有可能位模式都代表数字。这些要求不适用于其他类型。在任何特定的实现中,普通char对象可以采用与signed char或unsigned char相同的值;哪一个是由实现定义的。

0
据我所知,charsigned char在语义上是相同的,但编译器仍然认为它们是不同的。
不,char并不在语义上等同于signed char
与其他整数类型(integer、long、short等)相比,没有保证没有signedunsignedchar将是signed。这是实现定义的。一些架构将其定义为signed,而另一些则将其定义为unsigned
因此,对于char,如果有符号性很重要,您确实需要指定您想要的符号类型。
我的建议是,如果您正在进行字符操作等,或者使用使用charchar *的API调用,请使用char。如果您只想要一个8位整数值,请确保指定signed charunsigned char,这样在几年后当您移植到不同的架构时就不会遇到问题。

或者更好的方法是,使用uint8_tint8_t来表示8位整数。

编辑:根据您自己的答案:

这些要求对于其他类型不适用。在任何特定的实现中,一个普通的char对象可以采用与signed char unsigned char相同的值;哪一个是实现定义的。


-1

我会说出我所知道的...

对于char类型,C++中大小为'1'字节。

如果是有符号的char,则范围为-128到127;如果是无符号的char,则范围为0到256。

我们都知道一个字节中有8个位,在有符号的char情况下,最高位(即最左边的位)用于表示符号,其余7位用于表示值,使范围为0-2^7(0-127)。负数使用逻辑1表示,正数使用逻辑0表示。例如(1 0000111=-7,0 0000111=+7),而1 0000000表示-128。但是,如果将129分配给有符号的char值,则会自动更改为-127(即在范围(-128,127)内的值)。

另一种情况是无符号的char类型,所有8位都用于表示值,即范围为0-2^8(0-255)。这里的0-127与有符号的char相同,而属于-128到0的值可以在无符号char集合的128-255范围内找到。

因此,我们可以说并发现两种类型“有符号”和“无符号”的内部存储差异,这可能是问题所在。


谢谢你的回答,所有的都是正确的,但那并不是实际的问题 :) - Geoffroy
@Raon:实际上标准规定:sizeof(char) == 1,但并未确定1 => 1字节,而只是说明char是系统支持的最小可分配内存块。一些奇特的系统可能使用1KB作为最小可分配大小... 另外请注意,标准没有指定有符号类型的表示方式! - MFH
使用类型为'char *'的表达式初始化'signed char *'会在不同符号整数类型之间转换指针。 - Raon
@MFH 不是的,伙计,如果它只有一个字符,那就是一个。你所说的是操作系统的内存分配问题。但我们将为我们的程序使用更多的内存管理器。 - Raon
@Raon:1个字符并不等于1个字节,如果你声称相反,你可能需要与标准委员会交流(参见§1.7.1)。C++标准所谓的“字节”不一定是我们通常所说的字节... - MFH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接