关于c/c++中的64位整形数的一些心得

今天把实现与fpga通信的过程中碰到的一些问题集中罗列一下,做一个总结,让自己以后再碰到这些问题不再有疑问。

下面这些问题其实是理解计算机和程序最基本的问题,这些问题在《深入理解计算机系统》中有很深入的讨论,我就是在看完这本书的第三版的相关章节后才算是理解的比较清晰了。

1.关于64位整形数的问题。

fpga工程师给我的通信协议中有一个需要计算信号频率的公式是:下发数值=频率/10000000 * 2^32,

问题的关键是在2^32这,这个数的值大于了uint32类型能表示的最大的值了,uint32能表示的最大的整数值是(1<<32)-1,而2^32这个数等于(1<<32);所以必须用64位整形数来表示,在linux里可以用long long类型表示64位类型,windows vc中可以用unsigned __int64类型来表示,我在vs2015中写测试程序时这样写:

unsigned __int64 i = (1<<32);
printf("i=%I64d\n",i);

但是结果输出的却是0,纳闷了一阵子,后来明白了,输出0的原因出在(1<<32)这个表达式中,而如果我这么写就是正常的:

unsigned __int64 a = 1;
unsigned __int64 i = (a<<32);
printf("i=%I64d",i);
 

所以问题的原因是,在c/c++中常量的默认类型是什么,在上面的代码中表达式(1<<32)中,1会被编译器识别为一个32位的整形数,所以(1<<32)这个表达式的值会是0,然后这个32位整形值再被转为unsigned __int64的值还是0.所以我们可以强制把1这个常量转为64位整形数也是可以的:

unsigned __int64 i = ((unsigned __int64)1<<32);

由这个问题引申出32位有符号和无符号整形数可以表达的最大值和最小值,float和double能表示的最大值和最小值分别是多少?

2.unsigned int ,signed int,unsigned long int,signed long int,float,double这些类型的数分别能表示的最大值和最小值是多少呢?

这个问题其实每个现代编译器或sdk的头文件中都会有相关的定义,在windows平台上,我们以windows sdk 的BaseTsd.h头文件中的定义来看,因为这个头文件里面定义的比较容易理解,其他头文件比如c++ stl的头文件limits中也有类似的定义,BaseTsd.h中的相关宏定义如下:

#define MAXUINT8    ((UINT8)~((UINT8)0))
#define MAXINT8     ((INT8)(MAXUINT8 >> 1))
#define MININT8     ((INT8)~MAXINT8)

#define MAXUINT16   ((UINT16)~((UINT16)0))
#define MAXINT16    ((INT16)(MAXUINT16 >> 1))
#define MININT16    ((INT16)~MAXINT16)

#define MAXUINT32   ((UINT32)~((UINT32)0))
#define MAXINT32    ((INT32)(MAXUINT32 >> 1))
#define MININT32    ((INT32)~MAXINT32)

#define MAXUINT64   ((UINT64)~((UINT64)0))
#define MAXINT64    ((INT64)(MAXUINT64 >> 1))
#define MININT64    ((INT64)~MAXINT64)

#define MAXULONG32  ((ULONG32)~((ULONG32)0))
#define MAXLONG32   ((LONG32)(MAXULONG32 >> 1))
#define MINLONG32   ((LONG32)~MAXLONG32)

#define MAXULONG64  ((ULONG64)~((ULONG64)0))
#define MAXLONG64   ((LONG64)(MAXULONG64 >> 1))
#define MINLONG64   ((LONG64)~MAXLONG64)

#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#define MINLONGLONG ((LONGLONG)~MAXLONGLONG)

#define MAXSIZE_T   ((SIZE_T)~((SIZE_T)0))
#define MAXSSIZE_T  ((SSIZE_T)(MAXSIZE_T >> 1))
#define MINSSIZE_T  ((SSIZE_T)~MAXSSIZE_T)

#define MAXUINT     ((UINT)~((UINT)0))
#define MAXINT      ((INT)(MAXUINT >> 1))
#define MININT      ((INT)~MAXINT)

#define MAXDWORD32  ((DWORD32)~((DWORD32)0))
#define MAXDWORD64  ((DWORD64)~((DWORD64)0))

这种定义让程序员可以在数据的位级(bit)表示或二进制表示角度很好的理解。其中需要特别注意的就是有符号数的表示方法,这个问题在CSAPP这本书中也有很深入和清晰的讲解,从位级表示来说,有符号数的最小值的位级表示为符号位为1,其余为全为0,这个数就是有符号数的最小值,而如果有符号数的位级表示全为1,不管是8位16位32位还是64位,这个数的值就为-1.而有符号数的最大值就是无符号数的最大值再除以2,因为有符号数最高位要用作表示符号,不能贡献数值,所以除以2.

3.将一个整形数的某一位置零或置一的问题。

fpga通信协议中有许多命令需要通过位设置来实现不同的命令,比如使用一个字节的数据,不同的位代表不同的命令含义,最后实现都要用到如何设置一个整型数据的某个位bit.

首先,我们以unsigned int 32位例,写一个函数,置该数的某一位为1,可以这样写这个函数:

uint32 SetUint32Bit(uint32 v,uint8 bit_index)
{
    uint32 t;
    assert(bit_index<32);
    t = v |(1<<bit_index);
    return t;
}

uint32 ClearUint32Bit(uint32 v,uint8 bit_index)
{
    uint32 t;
    assert(bit_index<32);
    t = v&(~(1<<bit_index));
    return t;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值