uint8_t vs unsigned char
使用uint8_t
比C中的unsigned char
什么优势?
我知道在几乎所有的系统上, uint8_t
只是unsigned char
一个typedef,所以为什么要使用它呢?
它logging你的意图 – 你将存储小数字,而不是一个字符。
如果你使用其他types定义,如uint16_t
或int32_t
它看起来更好。
仅仅是迂腐,一些系统可能不具有8位types。 根据维基百科 :
当且仅当N = 8,16,32或64的types满足要求时,才需要一个实现来定义精确宽度的整数types。 不需要为其他N定义它们,即使它支持适当的types。
所以uint8_t
不能保证存在,虽然它将适用于所有8位= 1字节的平台。 一些embedded式平台可能会有所不同,但这是非常罕见的。 一些系统可能将char
types定义为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编译器工作。