来自C程序设计语言(Brian W. Kernighan),第2.7节 类型转换,第43页:
“有一个关于字符转整数的微妙问题。 ... 在某些机器上,左起第一位为1的字符将被转换为负整数。在其他机器上,则始终为正数。为了可移植性,如果要在char变量中存储非字符数据,请指定有符号或无符号。”
我的问题是:
为什么有人想要在char中存储非字符数据?(提供一个必须这样做的例子会很好)
当char转换为int时,为什么它的整数值会改变?
您能详细说明一下这个可移植性问题吗?
来自C程序设计语言(Brian W. Kernighan),第2.7节 类型转换,第43页:
“有一个关于字符转整数的微妙问题。 ... 在某些机器上,左起第一位为1的字符将被转换为负整数。在其他机器上,则始终为正数。为了可移植性,如果要在char变量中存储非字符数据,请指定有符号或无符号。”
我的问题是:
为什么有人想要在char中存储非字符数据?(提供一个必须这样做的例子会很好)
当char转换为int时,为什么它的整数值会改变?
您能详细说明一下这个可移植性问题吗?
关于1)
当人们需要一个数据流的字节缓冲区时,通常会使用char数组。虽然这不是很好的做法,但很多项目都在使用,只要你小心,就不会有太大问题。可能还有其他情况。
关于2)
当从较小的数据类型移动时,有符号整数经常被扩展。因此,11111111b(10进制中的-1)在扩展到32位时变为11111111 11111111 11111111 11111111。但是,如果char意图是无符号+255,则有符号整数可能最终变为-1。
关于可移植性3)
一些机器将char视为有符号整数,而另一些将其解释为无符号整数。这也可能基于编译器实现而异。大多数情况下,您不必担心它。Kernighan只是想帮助您了解细节。
我知道这是一个过时的问题,但您可以使用以下代码检查系统上的char是有符号还是无符号:
#include <limits.h> //Include implementation specific constants (MAX_INT, et c.)
#if CHAR_MAX == SCHAR_MAX
// Plain "char" is signed
#else
// Plain "char" is unsigned
#endif
1) 在C语言中,char
表示单个字节的大小,因此可用于存储任何类型的数据。例如,将图像加载到内存时,数据表示为char
数组。在现代代码中,我们通常使用诸如uint8_t
等typedefs更有用地指示缓冲区的目的,而不仅仅使用char
。
2&3)char
是带符号还是无符号取决于平台,因此如果程序依赖于此行为,则最好明确指定其中之一。
char
类型被定义为一个字节大小,即sizeof(char)
被定义为1
。这对于数据序列化非常有用。
char
的实现定义为unsigned char
或signed char
。现在想象一下char
表示smallint
。当从smallint
转换到int
时,你只是将一个小整数转换为一个大整数。问题是,你不知道那个smallint
是有符号还是无符号的。
我认为只要遵循《The C Programming Language》(K&R),就不会真正存在可移植性问题。
unsigned char
经常用于逐字节处理二进制数据。一个常见的例子是 UTF-8 字符串,它们不严格由“字符”组成。
如果有符号 char 是 8 位并且最高位被设置为 1,则表示它是负数。当将其转换为较大的类型时,通过将高位扩展到新类型的高位来保留符号。这被称为“符号扩展”赋值。
1) Char在所有系统中都实现为一个字节,因此它是一致的。
2) 在单字节整数中使用的位用于表示其符号。当系统上的int大于一个字节时,将char转换为int不会影响符号标志,否则会受到影响(还有带符号和无符号的char)。
3) 由于char实现的一致性,许多库像Intel IPP(Intel Performance Primitives)库及其同类OpenCV都使用它们。