c语言中数据类型所占用的位数,受到操作系统和编译器的影响,C语言中只有4中基本数据类型——整型、浮点型、指针和聚合类型(如数组和结构等);所有其他类型都是从这4种基本类型的某种变化或组合派生而来。

         整型、浮点型、指针、聚合类型受到操作系统和编译器的影响,而其在计算聚类类型的数据大小的时候还要注意内存对齐。

一、整型家族

整型家族包括charshort intintlong int,并且都分为signedunsigned型。

int型字长问题:

long int型至少应该和int型一样长,而int型至少应该和short int一样长。

     C/C++规定int字长和机器字长相同;

 操作系统字长和机器字长未必一致;

 编译器根据操作系统字长来定义int字长;

 

由上面三点可知,在一些没有操作系统的嵌入式计算机系统上,int的长度与处理器字长一致;有操作系统时,操作系统的字长与处理器的字长不一定一致,此时编译器根据操作系统的字长来定义int字长:“比如你在64位机器上运行DOS16系统,那么所有for dos16C/C++编译器中int都是16位的;在64位机器上运行win32系统,那么所有for win32C/C++编译器中int都是32位的”。(CPU字长是指其一条指令/一次运算可以处理的数据的最大宽度。

另外,对于整型的数值范围,每个编译器里面都有一个标准头文件:limits.h,这个头文件定义了一些宏,这些宏表示该编译器使用的所有数据类型的范围,编程过程中 使用这些宏就行了。例如你想要的int的最大值可以使用宏INT_MAX,最小值使用INT_MIN,而无符号则可以使用UINT_MAX,还有其它类型 的。你自己把这个头文件打开看看就知道了。

 

附:关于整形变量为32的问题的剖析:

 

整形变量是不是32位这个问题不仅与具体的CPU架构有关,而且 与编译器有关。在嵌入式系统的编程中,一般整数的位数等于CPU字长,常用的嵌入式CPU芯片的字长为81632,因而整形变量的长度可能是8 1632。在未来64位平台下,整形变量的长度可达到64位。

长整形变量的长度一般为CPU字长的2倍。

在数据结构的设计中,优秀的程序员并不会这样定义数据结构(假设为WIN32平台):

 

 1typedef struct tagTypeExample
 2{
 4    unsigned short x;
 6   unsigned int y; 
 8}
TypeExample;
 9
10

 

他们这样定义:

 

1 #define unsigned short UINT16 //16位无符号整数
2 #define unsigned int UINT32 //32位无符号整数
3 typedef struct tagTypeExample
4 {
5   UINT16 x;
6   UINT32 y; 
7 }TypeExample;
8 
9 

 

这样定义的数据结构非常具有通用性,如果上述32平台上的数据发送到16位平台上接收,在16位平台上仅仅需要修改UINT16UINT32的定义:

#define unsigned int UINT16 //16位无符号整数

#define unsigned long UINT32 //32位无符号整数

几乎所有的优秀软件设计文档都是这样定义数据结构的。

 

char型与程序可移植性:

char类型变量在本质上是小整型值。

字符型(char型)也分signed charunsigned char型,如果在定义变量时只使用关键字char,缺省情况下它根据编译器的定义为signed charunsigned char,这意味着不同机器上的char可能有不同的取值范围。因此,只有当程序使用的char型变量的值位于signed charunsigned char的交集中(例如编译器认为char8位二进制长时,这个交集是0~127ASCⅡ字符集的字符都在这个范围内),这个程序才是可移植的。

进一步,如果显示地将字符变量声明为signedunsigned,则可提高程序的可移植性,不过,有些机器处理signed charunsigned char的能力是不同的,硬性规定后可能会使效率受损,还有不少处理字符的库函数的参数声明为char,因此显示声明也可能会有兼容性问题。

结论:保证可移植性的最佳办法还是定义为char型同时只使用signed charunsigned char型的交集字符,在进行算术运算时,可根据需要再使用显示地声明或者强制转换。

二、聚合类型

自然对齐:对于基本数据类型(主要指整型、浮点型、指针)的变量不能简单的存储在内存中的任意地址处,它们的起始地址必须能够被他们的大小整除。

编译器必须确保不仅第一个元素要自然对齐,而且以后的每一个对象元素也要对齐才行,所以数组的自然对齐和单个元素的对齐要求是一样的。

例如

 

1 struct A{
2          char a;
3          int b;
4 };
5 Struct  A c;
6 

我们执行 sizeof(c)得到的是8,这是由于为了使得,a ,b 和c 都对齐,编译器为我们在char a后面填充了3个字节。所以在使用结构体时,元素放置的先后顺序会影响结构体的大小。

 

 

1 struct B                                    struct B1                                                            

{                                                   {                
2     char a;                                       char a;
3     char b;                                       int    c;
4     int c;                                          char b;
5 }                                                 }
6 

sizeof(struct B)等于8,而sizeof(struct B1)等于12;

另外我们可以使用#pragma pack(push,2)来指定字符对齐的边界。

部分引用 http://blog.chinaunix.net/u/26710/showart_404248.html

posted on 2010-02-23 09:58  Ruby_Wang  阅读(152)  评论(0编辑  收藏  举报