int8_t和char,哪个更好?

18

我知道这两者是不同类型(signed charchar),但是我的公司编码指南要求使用int8_t代替char

所以,我想知道,为什么我必须使用int8_t而不是char类型。有没有使用int8_t的最佳实践?


14
如果我记得正确,char 并不保证恰好是八位,这只是在大多数现代系统上恰巧是这样的。 - Some programmer dude
5
@JoachimPileborg 提到,char 的保证长度为一个字节。因此,char 中的位数取决于特定系统中字节的位数。 - triclosan
1
使用int8_t保证了任何平台上变量的大小为8位。 - suspectus
4
严谨地说,对于任何已定义的平台而言。有些平台不支持8位类型。 - Mike Seymour
3
你不应该询问公司其他人员那些指导方针背后的原因吗? - jalf
显示剩余9条评论
4个回答

20

在某些情况下,使用int8_t是完全可以的 - 具体来说,当需要使用带符号8位值进行计算时。涉及严格大小数据的计算 [例如,由外部要求定义为精确的8位结果] (我在上面的评论中使用了像素颜色级别,但那实际上应该是uint8_t,因为负像素颜色通常不存在 - 除非在YUV类型的颜色空间中)。

在字符串中,不应将类型int8_t用作char的替代。这可能会导致编译器错误(或警告,但我们真的不想处理编译器发出的警告)。例如:

int8_t *x = "Hello, World!\n";

printf(x);

在编译器A上可能能够正常编译,但在混合有符号和无符号字符值时,在编译器B上会出现错误或警告。或者如果 int8_t 甚至没有使用 char 类型。这就像期望

int *ptr = "Foo";

要在现代编译器中编译...

换句话说,如果您正在使用8位数据进行计算,则应该使用int8_t而不是char。将所有char替换为int8_t是不正确的,因为它们远非保证相同。

如果需要使用char用于字符串/文本等,如果由于某种原因char过于含糊(可能是有符号或无符号等),则应使用typedef char mychar; 或类似的东西。(可能可以找到比mychar更好的名称!)

编辑:我应该指出的是,不管你是否同意这一点,直接走向负责该公司“原则”的人,指着SO上的帖子说“我认为你错了”,这样做是相当愚蠢的。尝试理解动机。可能有更多的东西超出了我们的认知。


1
我对你的第二句话有异议。首先,由于整数提升,_所有_计算都将在int或更大的空间中进行。因此,您无疑是指当您必须在最小的空间中存储小的有符号值时。而对于这种情况,signed char可能更可取。在代码中看到int8_t的唯一时间是当类型必须与某些外部协议或硬件匹配时。(像素应该是uint24_t,每个颜色8位,但通常不存在。) - James Kanze
1
后来,如果char是16位,则int8_t将不存在。它必须是可寻址类型(而不是位域),并且要求char是最小的可寻址类型(当然,在该C/C++实现中支持:某些机器(例如VAX)支持寻址单个位)。 - James Kanze
非常好的问题描述,谢谢Mats Peterson。 - sokid
@JamesKanze 好的,我已经根据您的评论进行了修改。我认为我的信息的本质是非常清楚的:char不能替代int8_t,反之亦然 - 它们不应该互换使用。 - Mats Petersson
谢谢您的回答,我明白了。我的“mychar”首选名称是“ascii_t”,这个名称好吗? - sokid
显示剩余3条评论

14
他们只是提供不同的保证: char 保证存在,至少有8位宽度,并且能够表示介于-127和127之间的所有整数(如果是有符号的),或介于0和255之间的所有整数(如果是无符号的)。 int8_t 不保证存在(是的,有些平台上没有),但如果它存在,则保证为具有8位二进制补码的有符号整数类型,没有填充位;因此,它能够表示介于-128和127之间的所有整数,以及没有别的。
何时使用哪种类型?当类型所做的保证与您的要求相一致时。然而,值得注意的是,标准库的大部分部分需要char *参数,因此完全避免使用char似乎是短视的,除非有意决定避免使用这些库函数。

谁保证二进制补码?请提供参考资料。 - Kerrek SB
7
7.20.1.1 精确宽度整数类型,第1段:“typedef 名称 intN_t 表示宽度为 N、没有填充位和二进制补码表示法的有符号整数类型。”(强调为我所加)。 - Stephen Canon
1
@GrijeshChauhan:是的,在C语言中,“字节”被定义为“char的大小”,而char被定义为可寻址内存的最小单元。存在一些体系结构(主要是DSP),其中可寻址内存的最小单元为16、24或甚至32位。 - Stephen Canon
1
如果你的公司让你在字符串中使用int8_t,而实际上它是一个char值,那么是的。如果你想要一个小整数来进行计算(例如像素颜色值),那么使用int8_t是非常正确的选择。请注意,尽管在你的平台上使用int8_t *x = "Hello, World!\n"; printf(x);可能会编译成功,但在另一个平台上可能无法正常工作。 - Mats Petersson
1
@GrijeshChauhan 至少有一个相对现代的平台,其中字节为9位(而signed char是1的补码);它确实有一个C++编译器。我听说在一些嵌入式平台上,字节是16或32位。 - James Kanze
显示剩余8条评论

4

int8_t 只适用于需要恰好有8位且为带符号整数类型的代码,并且如果不存在这样的类型,则不应编译。这种要求比关于 int8_t 及其同类的问题更为罕见。大多数大小需求是类型至少具有特定数量的位。如果您需要至少8位,那么 signed char 就可以满足要求;int_least8_t也可以。


1

int8_t 在C99标准中被指定为恰好8位宽,并与其他C99保证宽度的类型相匹配。在需要精确8位有符号整数的新代码中应使用它。(不过,也可以看看 int_least8_tint_fast8_t。)

对于单字节字符字符串,仍然首选char作为元素类型,就像对于宽字符字符串,应该优先选择wchar_t作为元素类型。


stdint.h 包含了所有基本类型的 typedef,为什么它没有定义 'char' 类型? - sokid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接