在C语言中使用uint8_t比unsigned char有什么优势?
uint8_t
unsigned char
它记录了你的意图——你将存储小数字,而不是一个字符。
此外,如果你使用其他类型定义,如uint16_t或int32_t,它看起来更好。
uint16_t
int32_t
如你所说,“几乎每个系统”。
char可能是一个不太可能改变的,但一旦你开始使用uint16_t和朋友,使用uint8_t混合更好,甚至可能是编码标准的一部分。
char
在几乎每个系统上,我都遇到了uint8_t == unsigned char,但这不是由C标准保证的。如果你试图编写可移植的代码,它的确切大小是什么内存,使用uint8_t。否则使用unsigned char。
只是为了卖弄学问,有些系统可能没有8位类型。根据维基百科:
实现需要为N = 8,16,32或64定义精确宽度的整数类型,当且仅当它具有满足要求的任何类型时。不需要为任何其他N定义它们,即使它支持适当的类型。
所以uint8_t并不保证存在,尽管它适用于所有8位= 1字节的平台。一些嵌入式平台可能有所不同,但这种情况越来越少。一些系统可能将char类型定义为16位,在这种情况下可能不会有任何类型的8位类型。
除了这个(小)问题,在我看来@Mark Ransom的回答是最好的。使用最清楚地显示你使用数据的目的的那个。
另外,我假设你指的是uint8_t(在stdint.h头文件中提供的来自C99的标准类型定义)而不是uint_8(不属于任何标准)。
stdint.h
uint_8
有小。从可移植性的角度来看,char不能小于8位,并且不能小于char,因此如果给定的C实现具有无符号8位整型,则它将为char。或者,它可能根本没有,此时任何typedef技巧都是没有意义的。
typedef
它可以用来更好地记录您的代码,在某种意义上,很明显您需要8位字节,而不需要其他任何字节。但在实践中,几乎在任何地方这都是一个合理的期望(在DSP平台上,这是不正确的,但您的代码在那里运行的机会很小,并且您也可以在这样的平台上在程序顶部使用静态断言出错)。
关键在于编写与实现无关的代码。unsigned char不保证是8位类型。uint8_t是(如果可用)。
根据我的经验,有两个地方,我们想用uint8_t表示8位(和uint16_t等),我们可以有字段小于8位。在这两个地方,空间都很重要,在调试时,我们经常需要查看数据的原始转储,并需要能够快速确定它代表什么。
#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)))工作
是gcc's __attribute__((打包))/ #pragma包不安全?< / >
http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html