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

时间:2014-06-12 09:40:37

标签: c++ c

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

7 个答案:

答案 0 :(得分:8)

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

对于早期的C ++版本:

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

  • 如果您有效地获得了什么" byte"来自例如压缩流,数据库表备份文件,可执行映像,jpeg ...然后unsigned适用于上面提到的二进制数据内涵

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

    • 您无法将unsigned char*意外传递给期待char*的函数并将其作为假定文本进行操作

    • 在这些情况下,通常更自然地认为这些值在0..255的范围内,毕竟 - 为什么#"签署" bit对数据中的其他位有不同的意义吗?

  • 如果您正在存储"原始数据" - 在应用程序逻辑/设计级别恰好是8位数字数据,然后根据需要选择unsigned明确 signed char满足您的需求

答案 1 :(得分:4)

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

您获得的最重要的区别可能是您在访问缓冲区的各个元素时看到的行为,例如,用于打印。使用char,您可以获得实现定义的有符号或无符号行为;使用unsigned char,您总能看到未签名的行为。如果要打印“原始数据”缓冲区的各个字节,这一点很重要。

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

答案 2 :(得分:3)

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

如果您的值范围为[0,255],则应使用unsigned char,但如果为[-128,127],则应使用signed char

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

根据您的编译器或计算机类型,默认情况下char可能是未签名或签名的: Is char signed or unsigned by default? 因此具有char针对上述情况描述的范围。

如果您使用此缓冲区只是为了存储二进制数据而不使用它,那么使用charunsigned char之间没有区别。

修改

请注意,对于使用编译器标记的同一台计算机和编译器,您甚至可以change the default char

  

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

     

每种机器都有char的默认值。它默认为likeunsigned char或默认为signed char。   理想情况下,可移植程序在取决于对象的签名时应始终使用signed char或unsigned char。但很多   程序已被编写为使用普通字符并期望它   签名,或者希望它是未签名的,具体取决于他们的机器   写的。这个选项和它的逆,让你做这样的   程序使用相反的默认值。

     

类型char始终是每个signed char或unsigned char的不同类型,即使它的行为总是像   那两个。

答案 3 :(得分:1)

正如@Pablo在他的回答中所说的那样,关键的原因是,如果你对字节进行算术运算,那么你就会得到正确的&#39;如果您将字节声明为unsigned char,则会回答:您希望(在Pablo的示例中)100 + 100添加到200;如果您使用signed char(如果您的编译器上的char已签署,您可能会偶然做到这一点)总和,那么您无法保证 - 您要求麻烦。< / p>

另一个重要原因是,如果您明确说明哪些数据类型是什么,它可以帮助记录您的代码。声明

很有用
typedef unsigned char byte

甚至更好

#include <stdint.h>
typedef uint8_t byte

此后使用byte可以更清楚地了解您的程序的意图。根据您的编译器的偏执程度(-Wall是您的朋友),如果您向byte*函数提供char*参数,则此可能甚至会导致类型警告争论,从而促使你更仔细地思考你是否做了正确的事。

A&#39;字符&#39;从一个&#39;字节&#39;基本上是一个非常不同的东西。 C恰好模糊了这种区别(因为在C&#39; s级别,在大多数ASCII世界中,这种区别在许多情况下并不重要)。这种模糊并不总是有用,但它至少可以保持良好的智力卫生,以保持头脑中的差异。

答案 4 :(得分:0)

通常最好使用char,但它没那么重要。它是原始数据,所以你应该简单地传递它,而不是试图通过一种或另一种类型的char指针来处理它。由于char是本机数据类型,因此使用它是最有意义的,而不是想象您正在将数据强制为一种或另一种类型。

答案 5 :(得分:0)

如果您使用unsigned char,那么它只会使用有效的ASCII字符,因为它的范围将变为-127到+127。

你可以在这个问题中找到char和unsigned char细节之间的完全不同。

diff bet char and unsigned char

你可以看到这里的表格。

ASCII table

complete tables of raw characters

答案 6 :(得分:0)

如果能够使用C ++ 17,则有一种更适合处理原始数据的std :: byte类型。它只为它定义了按位逻辑运算符。