使用char或unsigned char数组存储原始数据更好吗?

M31*_*310 7 c c++

当需要在内存中缓冲一些原始数据时,例如从流中,是否更好地使用char或unsigned char数组?我总是使用char,但在工作中说它是更好的unsigned char,我不知道为什么......

Ton*_*roy 10

更新:引入了C++ 17 std::byte,它比使用任何方式更适合"原始"数据缓冲区char.

对于早期的C++版本:

  • unsigned char 强调数据不是"只是"文本

  • 如果您从压缩流,数据库表备份文件,可执行映像,jpeg ...获得了有效的"字节"数据,unsigned则适用于上面提到的二进制数据内涵

    • unsigned对于您可能想要对二进制数据执行的某些操作更好地工作,例如,对于有符号类型的某些位操作存在未定义和实现定义的行为,并且unsigned值可以直接用作数组中的索引

    • 你不能不小心将unsigned char*一个函数传递给一个期望的函数char*并让它作为假定的文本进行操作

    • 在这些情况下,通常更自然地认为值在0..255的范围内,毕竟 - 为什么"符号"位对数据中的其他位有不同的重要性?

  • 如果您正在存储"原始数据" - 在应用程序逻辑/设计级别恰好是8位数字数据,那么无论如何都要根据您的需要选择unsigned明确 选择signed char


Pab*_*lgo 5

在内部,它完全相同:每个元素都是一个字节。当您使用这些值进行操作时会给出差异。

如果你的值范围是 [0,255] 你应该使用unsigned char但如果它是 [-128,127] 那么你应该使用signed char.

假设您使用的是第一个范围 ( signed char),那么您可以执行操作100+100。否则该操作将溢出并为您提供意想不到的值。

根据您的编译器或机器类型,char默认情况下可能是无符号或有符号的:默认情况下 char 是有符号还是无符号? 因此具有char针对上述情况描述的范围。

如果您仅使用此缓冲区来存储二进制数据而不对其进行操作,则使用char或之间没有区别unsigned char

编辑

请注意,您甚至可以使用编译器的标志更改 char同一台机器和编译器的默认值

-funsigned-char 让类型 char 为无符号,如 unsigned char。

每种机器都有一个默认字符应该是什么。它要么默认类似于无符号字符,要么默认类似于有符号字符。理想情况下,可移植程序在依赖于对象的签名时应始终使用有符号字符或无符号字符。但是许多程序被编写为使用普通字符并期望它有符号,或者期望它是无符号的,这取决于它们被编写的机器。此选项及其反选项可让您使用相反的默认设置使此类程序工作。

类型 char 总是与每个有符号字符或无符号字符不同的类型,即使它的行为总是就像这两者之一。

  • “如果是 [-127,127] 使用 `char`。” `char` 也可能是无符号的,如果你需要有符号,请使用 `signed char`。“……给你一个负数。” 也许,也许不是,签名溢出是 UB。 (2认同)

das*_*ght 5

就缓冲区的结构而言,没有区别:在这两种情况下,您都会获得一个字节的元素大小,这是标准规定的。

也许您得到的最重要的区别是访问缓冲区的各个元素时所看到的行为,例如,用于打印。有了char实现定义的有符号或无符号行为;与unsigned char你总能看到未签名的行为。如果您想打印“原始数据”缓冲区的各个字节,这将变得很重要。

用于缓冲区的另一个很好的替代方法是精确宽度整数uint8_t。它保证与 具有相同的宽度unsigned char,它的名称需要较少的输入,并且它告诉读者您不打算将缓冲区的各个元素用作基于字符的信息。