要确定系统的字节顺序,我计划在变量中存储多字节整数值,并通过unsigned char
访问第一个字节包裹在union
;例如:
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_t
,uint16_t
等。)
C99标准保证的C数据类型是否至少有两个字节?
PS 假设unsigned int
实际上大于一个字节,我的union
会表现得像我期望的那样(变量first_byte
访问所有C99兼容平台上的变量val
中的第一个字节?
答案 0 :(得分:4)
由于int
的范围必须至少为16位,因此int
在大多数实际系统中都符合您的标准。 short
(以及long
和long long
)也是如此。如果您只需要16位,则必须查看int16_t
中是否声明了uint16_t
和<stdint.h>
。
如果您担心CHAR_BIT
大于8的系统,那么您必须更加努力。如果CHAR_BIT
为32,则只保证long long
包含两个字符。
在评论中,Richard J Ross III说:
标准对int的大小一无所知,除了它必须大于或等于short之外,例如,在我工作的某些系统上它可能是10位。
相反,C标准具有不同类型必须支持的范围下限的规范,而具有10位int
的系统不符合C。
具体而言,在ISO / IEC 9899:2011§5.2.4.2.1整数类型的大小<limits.h>
中,它说:
¶1下面给出的值应替换为适用于
#if
的常量表达式 预处理指令。此外,CHAR_BIT
和MB_LEN_MAX
除外 以下内容应替换为与a相同类型的表达式 表达式,它是根据整数转换的相应类型的对象 促销活动。它们的实现定义值的大小应相等或更大 (绝对值)显示的那些,具有相同的符号。- 最小对象不是位字段(字节)的位数
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
答案 1 :(得分:4)
GCC提供了一些宏,给出了系统的字节序:GCC common predefined macros
示例(来自提供的链接):
/* Test for a little-endian machine */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
当然,这仅在您使用gcc时才有用。此外,有条件的字节序编译可能被认为是有害的。这是一篇很好的文章:The byte order fallacy。
我更愿意使用常规条件让编译器检查另一种情况。即:
if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
...
答案 2 :(得分:3)
不,没有任何东西可以保证大于一个字节 - 但是保证没有(非位域)类型小于而不是一个字节,并且一个字节可以保持256个不同的值,如果您有int8_t
和int16_t
,那么保证int8_t
是一个字节,因此int16_t
必须是两个字节。
答案 3 :(得分:2)
C标准仅保证char <= short <= int <= long <= long long
[和unsigned
]的大小。因此,从理论上讲,可能存在所有尺寸只有一种尺寸的系统。
如果在某些特定架构上出现这种情况并不是很重要,那么我会添加一段代码来代码if (sizeof(char) == sizeof(int)) exit_with_error("Can't do this....");
。
在几乎所有机器中,int
或short
应该完全没问题。我实际上并不知道char
和int
大小相同的任何机器,但我确信它们确实存在。那些机器也可能有本机byte
!= 8位,如9位或14位,以及14,18或36或28位的字......
答案 4 :(得分:0)
查看stdint.h的手册页(uint_least16_t
2个字节)
答案 5 :(得分:0)
至少根据http://en.wikipedia.org/wiki/C_data_types - int的大小保证是两个“char”长。所以,这个测试应该有效,尽管我想知道是否有更合适的解决方案。例如,除了极少数例外,大多数体系结构的endianness都设置为编译时,而不是运行时。但是有一些架构可以切换字节序(我相信ARM和PPC是可配置的,但ARM传统上是LE,而PPC主要是BE)。
答案 6 :(得分:0)
符合标准的实现可以使其所有基本类型的大小为1(并且至少保存32位数据)。然而,对于这样的实现,字节序的概念不适用。
没有什么能禁止符合要求的实现,例如,little-endian short
和big-endian long
。
因此,每种积分类型有三种可能的结果:它可以是big-endian,little-endian或size.1。分别检查每种类型以获得最大的理论可移植性。在实践中,这可能永远不会发生。
中端类型,例如理论上,只有偶数页面上的大端内容才有可能,但我甚至不会考虑这样的实现。
答案 7 :(得分:0)
虽然答案基本上是“否”,但满足stdio函数的接口要求要求范围[0,UCHAR_MAX]适合int
,这会产生sizeof(int)
更大的隐式要求在托管实现上超过1(独立实现可以省略stdio,并且他们没有理由不能拥有sizeof(int)==1
)。所以我认为假设sizeof(int)>1
是相当安全的。