起因
今天无意间在console中执行'1'-'0'的运算,意外的打印出了1,是number类型的,难道字符串也能相减?计算机内部是如何将String'1'转为Number1的?
字符串'1'在计算机中的表示
'1'在计算机中是由ASCII 0x31表示的(百度ASCII)键盘上的所有键都有对应的ASCII码。
'1'转为1的过程
首先贴一段c的代码:
#include <stdio.h>
int my_atoi(char* pstr)
{
int integer=0,sign;//定义整形数和符号数
if(pstr == NULL)
return -1;
while(*pstr==' ') //跳过前面的空格字符
pstr++;
//判断正负号 如果是正号,指针指向下一个字符 如果是符号,把符号标记为Integer_sign置-1,然后再把指针指向下一个字符
sign = (*pstr =='-')? -1:1;
if(*pstr == '-' || *pstr == '+')
pstr++;
//把数字字符串逐个转换成整数,并把最后转换好的整数赋给Ret_Integer
while(*pstr >= '0' && *pstr <= '9')
{
integer = integer * 10 + *pstr - '0';
pstr++;
}
return integer*sign;
}
char *my_itoa(int num)
{
int i = 0,j=0,sign = num;
char temp[100],str[100]; //temp用来取每个数字字符 ,str用来存逆序的字符串
if((sign = num) < 0) //如果是负数,先转为正数
{
num = -num;
}
do //从各位开始变为字符,直到最高位,最后应该反转
{
temp[i++] = num%10 + '0';
num = num/10;
}while(num > 0);
if(sign < 0) //如果是负数,补上负号
{
temp[i++] = '-';
}
temp[i] = ' '; //最后加上字符串结束符
//将存储的字符反转
//printf("%s
",temp);//for test
i--;
while(i>=0)
{
str[j] = temp[i];
j++;
i--;
}
str[j]= ' ';
return str;
}
int main(void)
{
char *str ="-123";
printf("%d
",my_atoi(str));
char *s =my_itoa(-456);
printf("%s
",s);
return 0;
}
my_atoi函数是String转Number的,*my_itoa
函数是Number转String。my_atoi函数中我们最主要看integer = integer * 10 + *pstr - '0';
这一行代码中的*pstr - '0'
,通过阅读代码*pstr
表示字符串'0'-'9'的值,那么当*pstr
等于'1'时,*pstr - '0'
代码就是'1' - '0'
,通过转成ASCII0x31 - 0x30
等于1,这时的1就是number类型的1,这就是计算机内部'1'到1的转换过程,其他数字转换也类似。
(PS:这里只是为了解释转换过程,Number类型123是通过个位是3、十位是2、百位是1,各个位数的值通过*pstr - '0'
转成'123')
1转为'1'的过程
同理我们看*my_itoa
函数temp[i++] = num%10 + '0';
这一行代码中的num%10 + '0'
如果num等于1,那么1 + '0'
转成ASCII1 + 0x30
等于0x31,也就是字符串'1'对应的ASCII码。
总结
其实在console中'1'-'0'
就是0x31 - 0x30
,那么问题来了为什么'A'-'0'
等于0x40 - 0x30
按文章的逻辑来说应该是10,为什么会NaN?我想这可能是js语言内部做的限制,只能'0'-'9'的字符串去转换。(文章是个人的理解,有哪里解释的不正确请指正)