是否保证C99数据类型至少为两个字节?

时间:2012-12-27 16:51:15

标签: c memory types c99 endianness

要确定系统的字节顺序,我计划在变量中存储多字节整数值,并通过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_tuint16_t等。)

C99标准保证的C数据类型是否至少有两个字节?

PS 假设unsigned int实际上大于一个字节,我的union会表现得像我期望的那样(变量first_byte访问所有C99兼容平台上的变量val中的第一个字节?

8 个答案:

答案 0 :(得分:4)

由于int的范围必须至少为16位,因此int在大多数实际系统中都符合您的标准。 short(以及longlong long)也是如此。如果您只需要16位,则必须查看int16_t中是否声明了uint16_t<stdint.h>

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


C标准对整数类型的大小的描述

在评论中,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_BITMB_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_tint16_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....");

在几乎所有机器中,intshort应该完全没问题。我实际上并不知道charint大小相同的任何机器,但我确信它们确实存在。那些机器也可能有本机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是相当安全的。