0

为了确定系统的字节顺序,我计划将一个多字节整数值存储在一个变量中,并通过一个包裹在 a 中的来访问第一个字节;例如:unsigned charunion

union{
    unsigned int val;
    unsigned char first_byte;
} test;

test.val = 1; /* stored in little-endian system as "0x01 0x00 0x00 0x00" */

if(test.first_byte == 1){
    printf("Little-endian system!");
}else{
    printf("Big-endian system!");
}

我想让这个测试跨平台移植,但我不确定 C99 标准是否保证unsigned int数据类型的大小大于一个字节。此外,由于“C 字节”在技术上不必是 8 位大小,因此我不能使用精确宽度的整数类型(例如uint8_tuint16_t等)。

C99 标准是否保证任何 C 数据类型的大小至少为两个字节?

PS假设 anunsigned int实际上大于一个字节,在所有 C99 兼容平台上,我的union行为是否符合我的预期(变量first_byte访问 variable 中的第一个字节)?val

4

8 回答 8

4

由于int必须具有至少 16 位的范围,int因此将满足您在大多数实际系统上的标准。short(和long, 和)也是如此long longint16_t如果您想要正好 16 位,则必须查看是否uint16_t<stdint.h>.

如果您担心CHAR_BIT大于 8 的系统,那么您必须更加努力。如果CHAR_BIT是 32,则只能long long保证容纳两个字符。


C 标准对整数类型大小的规定

理查德 J 罗斯三世在评论中说:

该标准绝对没有说明 int 的大小,只是它必须大于或等于 short,因此,例如,在我工作过的某些系统上它可能是 10 位。

相反,C 标准对不同类型必须支持的范围的下限有规定,10 位的系统int不会符合 C。

具体来说,在 ISO/IEC 9899:2011 §5.2.4.2.1 Sizes of integer types<limits.h>中,它说:

¶1 下面给出的值应替换为适用于#if 预处理指令的常量表达式。此外,除了CHAR_BITand之外MB_LEN_MAX,以下内容应替换为与作为根据整数提升转换的相应类型的对象的表达式具有相同类型的表达式。它们的实现定义值的大小(绝对值)应等于或大于所示值,符号相同。

— 不是位域的最小对象的位数(字节) CHAR_BIT 8

[...]

— 类型对象的最小值short int

SHRT_MIN -32767// -(2 15 - 1)

— 类型对象的最大值short int

SHRT_MAX +32767// 2 15 - 1

— 类型对象的最大值unsigned short int

USHRT_MAX 65535// 2 16 - 1

— 类型对象的最小值int

INT_MIN -32767// -(2 15 - 1)

— 类型对象的最大值int

INT_MAX +32767// 2 15 - 1

— 类型对象的最大值unsigned int

UINT_MAX 65535// 2 16 - 1

于 2012-12-27T16:58:10.733 回答
4

GCC 提供了一些宏来给出系统的字节顺序:GCC 通用预定义宏

示例(来自提供的链接):

/* Test for a little-endian machine */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

当然,这仅在您使用 gcc 时才有用。此外,字节序的条件编译可以被认为是有害的。这是一篇很好的文章:字节顺序谬误

我宁愿使用常规条件来让编译器检查另一种情况。IE:

if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
...
于 2012-12-27T17:08:38.127 回答
3

不,什么都不能保证大于一个字节——但可以保证没有(非位域)类型小于一个字节,并且一个字节可以容纳 256 个不同的值,所以如果你有 anint8_t和 an int16_t,那么保证int8_t是一个字节,所以int16_t必须是两个字节。

于 2012-12-27T16:59:02.590 回答
2

C 标准只保证 char <= short <= int <= long <= long long[ 和unsigned] 的大小。因此,理论上,可能存在对于所有尺寸只有一种尺寸的系统。

如果在某些特定架构上不会出错真的很重要,我会添加一段代码来对代码执行类似if (sizeof(char) == sizeof(int)) exit_with_error("Can't do this....");的操作。

在几乎所有机器中,int或者short应该完全没问题。我实际上并不知道任何机器charint大小相同,但我 99% 确信它们确实存在。那些机器也可能有它的本机byte!= 8 位,例如 9 或 14 位,以及 14、18 或 36 或 28 位的字......

于 2012-12-27T17:03:46.090 回答
0

查看stdint.h的手册页(uint_least16_t2 个字节)

于 2012-12-27T16:55:02.367 回答
0

至少根据http://en.wikipedia.org/wiki/C_data_types - int 的大小保证为两个“char”长。所以,这个测试应该可以工作,尽管我想知道是否有更合适的解决方案。一方面,除了极少数例外,大多数架构的字节序都设置在编译时,而不是运行时。不过,有一些架构可以切换字节顺序(我相信 ARM 和 PPC 是可配置的,但 ARM 传统上是 LE,而 PPC 主要是 BE)。

于 2012-12-27T16:58:38.643 回答
0

A conforming implementation can have all its fundamental types of size 1 (and hold at least 32 bits worth of data). For such an implementation, however, the notion of endianness is not applicable.

Nothing forbids a conforming implementation to have, say, little-endian shorts and big-endian longs.

So there are three possible outcomes for each integral type: it could be big-endian, little-endian, or of size 1. Check each type separately for maximum theoretical portability. In practice this probably never happens.

Middle-endian types, or e.g. big-endian stuff on even-numbered pages only, are theoretically possible, but I would refrain from even thinking about such an implementation.

于 2012-12-27T17:25:07.873 回答
0

While the answer is basically "no", satisfying the interface requirements for the stdio functions requires that the range [0,UCHAR_MAX] fit in int, which creates an implicit requirement that sizeof(int) is greater than 1 on hosted implementations (freestanding implementations are free to omit stdio, and there's no reason they can't have sizeof(int)==1). So I think it's fairly safe to assume sizeof(int)>1.

于 2014-04-26T22:23:36.680 回答