uint8_t vs unsigned char

使用uint8_t比C中的unsigned char什么优势?

我知道在几乎所有的系统上, uint8_t只是unsigned char一个typedef,所以为什么要使用它呢?

它logging你的意图 – 你将存储小数字,而不是一个字符。

如果你使用其他types定义,如uint16_tint32_t它看起来更好。

仅仅是迂腐,一些系统可能不具有8位types。 根据维基百科 :

当且仅当N = 8,16,32或64的types满足要求时,才需要一个实现来定义精确宽度的整数types。 不需要为其他N定义它们,即使它支持适当的types。

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

除了这个小问题, @Mark Ransom的回答在我看来是最好的。 使用最清楚地显示你正在使用的数据。

另外,我假设你的意思是uint8_t (来自stdint.h头文件中提供的C99的标准typedef),而不是uint_8 (不是任何标准的一部分)。

整个过程就是编写与实现无关的代码。 unsigned char不能保证是一个8位的types。 uint8_t是。

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

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

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

首先是RF协议,特别是在窄带系统中。 在这种环境下,我们可能需要将尽可能多的信息收集到一条消息中。 第二个是闪存,我们的空间可能非常有限(如embedded式系统)。 在这两种情况下,我们都可以使用打包的数据结构,编译器会负责打包和解包:

 #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() 

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

有一些使用打包结构的警告。 最大的问题是你必须避免提取成员的地址。 在多字节alignment的单词的系统上,这可能会导致错误的exception – 和coredump。

有些人也会担心表演,并认为使用这些包装结构会减慢你的系统。 确实,在幕后,编译器添加了访问未alignment数据成员的代码。 您可以通过查看IDE中的汇编代码来看到。

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

以下是一些相关的讨论:

编译包(1)也不__attribute__((aligned(1)))工作

是gcc的__attribute __((packed))/ #pragma pack不安全?

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

有一点。 从可移植性的angular度来说, char不能小于8位,并且没有什么可以小于char ,所以如果一个给定的C实现有一个无符号的8位整数types,它将是char 。 或者,它可能根本没有一个,此时任何typedef技巧都是没有意义的。

它可以被用来更好地logging你的代码,因为很明显你需要8位字节而没有其他的东西。 但是在实践中,这实际上已经是一个合理的期望了(有些DSP平台并不是真实的,但是你的代码在那里运行的机会很渺茫,而且你也可以在程序的顶部使用静态断言这样一个平台)。

在几乎所有我遇到的系统中,uint8_t == unsigned char,但这不是C标准保证的。 如果您正在尝试编写可移植代码,并且它确切地说明了内存的大小,请使用uint8_t。 否则使用无符号字符。

例如,在编写networking分析器时,这非常重要。 包头由协议规范定义,而不是由特定平台的C编译器工作。