uint8_t vs unsigned char

时间:2009-11-12 22:28:23

标签: c typedef

在C中使用uint8_t优于unsigned char的优势是什么?

我知道几乎每个系统uint8_t都只是unsigned char的typedef, 那么为什么要用呢?

8 个答案:

答案 0 :(得分:204)

它记录了你的意图 - 你将存储小数字而不是字符。

如果您使用uint16_tint32_t等其他类型设置,它看起来也会更好。

答案 1 :(得分:63)

只是迂腐,有些系统可能没有8位类型。根据{{​​3}}:

  

当且仅当它具有满足要求的任何类型时,才需要实现为N = 8,16,32或64定义精确宽度整数类型。即使它支持适当的类型,也不需要为任何其他N定义它们。

所以uint8_t不能保证存在,尽管它适用于8位= 1字节的所有平台。一些嵌入式平台可能会有所不同,但这种情况非常罕见。有些系统可能将char类型定义为16位,在这种情况下,可能不会是任何类型的8位类型。

除了(次要)问题,Wikipedia在我看来是最好的。使用最清楚地显示您正在使用数据的那个。

另外,我假设您的意思是uint8_tstdint.h标题中提供的C99标准typedef)而不是uint_8(不是任何标准的一部分)。

答案 2 :(得分:40)

重点是编写与实现无关的代码。 unsigned char不保证是8位类型。 uint8_t是(如果可用)。

答案 3 :(得分:7)

正如你所说,“几乎每个系统”。

char可能是不太可能改变之一,但是一旦你开始使用uint16_t和朋友,使用uint8_t混合更好,甚至可能是编码标准的一部分。

答案 4 :(得分:7)

根据我的经验,有两个地方我们想要使用uint8_t来表示8位(和uint16_t等),并且我们可以使用小于8位的字段。这两个地方都是空间问题,我们经常需要在调试时查看数据的原始转储,并且需要能够快速确定它所代表的内容。

第一种是RF协议,特别是在窄带系统中。在这种环境中,我们可能需要尽可能多地将信息打包到单个消息中。第二个是闪存存储,我们的空间可能非常有限(例如在嵌入式系统中)。 在这两种情况下,我们都可以使用打包数据结构,编译器将在其中处理打包和解包:

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

您使用哪种方法取决于您的编译器。您可能还需要支持具有相同头文件的多个不同编译器。这种情况发生在设备和服务器可能完全不同的嵌入式系统中 - 例如,您可能拥有与x86 Linux服务器通信的ARM设备。

使用打包结构有一些注意事项。最大的问题是你必须避免取消引用成员的地址。在具有多字节对齐单词的系统上,这可能导致未对齐的异常 - 以及coredump。

有些人也会担心性能,并认为使用这些打包结构会降低系统速度。确实,在幕后,编译器添加了访问未对齐数据成员的代码。您可以通过查看IDE中的汇编代码来查看。

但是由于打包结构对于通信和数据存储最有用,因此在内存中处理数据时可以将数据提取为非打包表示。 通常我们无需在内存中处理整个数据包。

以下是一些相关的讨论:

pragma pack(1) nor __attribute__ ((aligned (1))) works

Is gcc's __attribute__((packed)) / #pragma pack unsafe?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html

答案 5 :(得分:6)

没什么。从可移植性的角度来看,char不能小于8位,也不能小于char,所以如果给定的C实现有一个无符号的8位整数类型,它将是{{1 }}。或者,它可能根本没有一个,此时任何char技巧都没有实际意义。

它可用于更好地记录您的代码,因为很明显您需要8位字节而不需要其他内容。但实际上它几乎已经在任何地方都是合理的期望(有些DSP平台并不是真的,但是你的代码在那里运行的可能性很小,你也可以在你的程序顶部使用静态断言错误输出这样的平台)。

答案 6 :(得分:3)

这对于编写网络分析器非常重要。 数据包标头由协议规范定义,而不是由特定平台的C编译器工作的方式定义。

答案 7 :(得分:2)

在几乎每个系统上我都遇到过uint8_t == unsigned char,但C标准并不能保证这一点。如果您正在尝试编写可移植代码,并且确切地知道内存的大小,请使用uint8_t。否则使用unsigned char。