Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1641263
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3943
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: C/C++

2011-12-26 19:33:54

摘要:

    在实际编程中,通常取该数据类型表示范围最大的值模拟无穷大。若是系统数据类型,则可以直接用limits.h的宏,但如果是自定义的数据类型,则需自行定义。本文介绍一种定义可移植无穷大的方法,即用(相关数据类型-1)得到该数据类型的最大值。


    便于移植就是尽可能地屏蔽硬件差异,这一点在嵌入式开发尤为重要,因为相对于PC,嵌入式微控制器架构种类繁多(如ARM、MIPS、AVR、PowerPC),位数种类也多(4/8/16/32)。为了有更好的移植性,除了考虑平台间的控制方式(比如大小端),还需明确变量的数据类型(比如字符值是带符号的还是不带符号的)。

一、变量的数据类型

    C语言中只有4中基本数据类型--整型、浮点型、指针和聚合类型(如数组和结构等),所有其他类型都是从这4种基本类型的某种变化或组合派生而来[1]。整型家族包括char、short int、int和long int,并且都分为signed和unsigned型[1]。

1.1 int型字长问题[1]

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

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

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

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

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

1.2 宏定义

    为了获得更好的移植性,可以将数据类型重新定义在一个新的文件,比如定义16位和32位无符号整数,在32位平台定义如下:

  1. #define unsigned short UINT16 //16位无符号整数

  2. #define unsigned int UINT32 //32位无符号整数

    当修改移植到其他平台,只需修改这个文件相关的数据类型定义,比如移植到16位平台,更改定义如下:

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

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


二、无穷大

    C语言没有所谓无穷大,但实际编程偶尔会用到。通常取该数据类型表示范围最大的值模拟无穷大,比如32位的int,最大值0x7FFFFFFF。对于整型的数值范围,每个编译器里面都有一个标准头文件:limits.h,这个头文件定义了一些宏,这些宏表示该编译器使用的所有数据类型的范围,编程过程中 使用这些宏就行了。比如int的最大值可以使用宏INT_MAX,最小值使用INT_MIN[1]。

    默认的数据类型可以在limits.h文件找到现成的宏,但如果是自定义的数据类型,该如何定义最大值,以获得更好的移植性呢。最近在分析Coffee文件系统找到答案,部分源码如下:

  1. #if COFFEE_PAGES <= 127
  2.   #define coffee_page_t u8_t
  3. #elif COFFEE_PAGES <= 0x7FFF
  4.   #define coffee_page_t u16_t
  5. #endif

  6. #define INVALID_PAGE ((coffee_page_t)-1)

    当coffee_page_t是8位的时候,INVALID_PAGE为0xFF,当coffee_page_t是16位的时候,INVALID_PAGE为0xFFFF。如此,INVALID_PAGE可以自适应coffee_page_t类型的变化,具有很好的移植性。

我在PC Linux平台模拟了效果,源码如下:

  1. #include <stdio.h>

  2. //typedef unsigned int coffee_page_t
  3. #define coffee_page_t unsigned int
  4. //#define coffee_page_t unsigned short int

  5. #define INVALID_PAGE ((coffee_page_t)-1)
  6. int main()
  7. {
  8.   printf("0x%X\n", INVALID_PAGE);
  9.   return 0;
  10. }

运行结果如下:

    当coffee_page_t是unsigned short int时,输出0xFFFF。我思考良久,这样用的理论依据是什么。后来,跟邻座的斌讨论,他说会不会coffee_page_t被当成0了,而计算机又是按补码表示,coffee_page_t-1就等于0xFFFFFFFF(因为是无符号)。我想这是很合理的解释。


弱弱问一个问题,在上例我用typedef unsigned int INT32U,为何编译出错?求指点,错误信息如下:


参考资料:

[1] 博文《int型长度

阅读(4022) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~