uint8_t相对于unsigned char有什么优势?

xzv2uavs  于 2023-10-16  发布在  其他
关注(0)|答案(8)|浏览(169)

在C中使用uint8_tunsigned char有什么好处?
我知道在几乎所有的系统上uint8_t都只是unsigned char的typedef,那么为什么要使用它呢?

carvr3hs

carvr3hs1#

它记录了您的意图-您将存储小数字,而不是字符。
如果你使用其他类型的定义,比如uint16_tint32_t,它看起来也更好。

disbfnqx

disbfnqx2#

有些系统可能没有8位类型。根据Wikipedia
当且仅当一个实现具有满足要求的任何类型时,它需要为N = 8、16、32或64定义精确宽度的整数类型。不需要为任何其他N定义它们,即使它支持适当的类型。
所以uint8_t不能保证存在,尽管它在所有8位= 1字节的平台上都存在。一些嵌入式平台可能会有所不同,但这已经非常罕见了。有些系统可能将char类型定义为16位,在这种情况下,可能不会有任何类型的8位类型。
除了那个(小)问题,@Mark Ransom的回答在我看来是最好的。使用一个最清楚地表明你正在使用的数据。
此外,我假设您指的是uint8_t(在stdint.h头文件中提供的C99标准typedef)而不是uint_8(不属于任何标准)。

ecfsfe2w

ecfsfe2w3#

关键是要写独立于实现的代码。unsigned char不保证是8位类型。uint8_t是(如果可用)。

d6kp6zgx

d6kp6zgx4#

就像你说的,“几乎所有的系统”。
char可能是不太可能改变的一个,但是一旦你开始使用uint16_t和朋友,使用uint8_t混合更好,甚至可能是编码标准的一部分。

j2cgzkjk

j2cgzkjk5#

几乎没有。从可移植性的Angular 来看,char不能小于8位,并且没有任何东西可以小于char,因此如果给定的C实现具有无符号8位整数类型,则它将是char。或者,它可能根本没有一个,在这一点上,任何typedef技巧都是没有意义的。
它可以用来更好地记录你的代码,在某种意义上,很明显,你需要8位字节,没有别的。但在实践中,这是一个合理的期望,几乎任何地方都已经(有DSP平台上,这不是真的,但你的代码在那里运行的机会很小,你也可以在这样的平台上在程序的顶部使用静态Assert)。

o4tp2gmn

o4tp2gmn6#

在我的经验中,有两个地方我们想要使用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设备。
使用打包结构有一些注意事项。最大的问题是必须避免取消引用成员的地址。在具有多字节对齐字的系统上,这可能导致未对齐异常和核心转储。
有些人也会担心性能,并认为使用这些打包结构会降低系统的速度。的确,在幕后,编译器添加代码来访问未对齐的数据成员。您可以通过查看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

ocebsuys

ocebsuys7#

这是非常重要的,例如当你写一个网络分析器。数据包报头是由协议规范定义的,而不是由特定平台的C编译器的工作方式定义的。

vu8f3i0k

vu8f3i0k8#

在几乎所有的系统上,我都遇到过uint8_t == unsigned char,但C标准并不保证这一点。如果你正在尝试编写可移植的代码,并且内存的大小很重要,请使用uint8_t。否则使用unsigned char。

相关问题