/******************************************************
Reference the <<c interface and implementation>>
chapter 3 atom
*******************************************************/
char *int_2_str(long n) {
static char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n == LONG_MIN)
m = LONG_MAX + 1UL;
else if (n < 0)
m = -n;
else
m = n;
do
*--s = m % 10 + '0';
while ((m /= 10) > 0);
if (n < 0)
*--s = '-';
return s;
}
关于该算法的两个问题:
1、为什么要将负数转化为正数?
因为无符号数的除法和求余都有良好的定义,而有符号数存在不确定性;
参考如下:
有符号数与无符号数的除法
这样一个问题:
int a = -2; printf("%d,%d", a/4*4, a/4U*4);
打印出的是:0,-4
有符号数与无符号数做除法时,双方都转为无符号数再做除法;
-2在计算机中的存储形式为:0xff ff ff fe
作为无符号数除以4时,向右移2位(左边补零),中间结果为0x3f ff ff ff
之后乘以4时,向左移位(右边补零),结果为oxff ff ff fc
该数字表示有符号数-4,于是-4就被打印出来。
2、对于最小整数(LONG_MIN)为什么需要特殊处理?
由于二进制补码数的不对称性,在二进制补码系统中,负数比正数多一个,因此不能对LONG_MIN 直接取负数(-LONG_MIN)转化为无符号正数, 因为将-LONG_MIN 赋值给一个无符号整数会溢出(unsigned long m=-LONG_MIN;// 溢出)。所以LONG_MIN 的绝对值不可能被表示出来。
在 limits.h 有如下宏定义:
#define LONG_MAX 2147483647L
#define LONG_MIN (-LONG_MAX-1)
#define ULONG_MAX 0xffffffffUL