起因
今天無意間在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] = '\0'; //最后加上字符串結束符
//將存儲的字符反轉
//printf("%s\n",temp);//for test
i--;
while(i>=0)
{
str[j] = temp[i];
j++;
i--;
}
str[j]= '\0';
return str;
}
int main(void)
{
char *str ="-123";
printf("%d\n",my_atoi(str));
char *s =my_itoa(-456);
printf("%s\n",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'的字符串去轉換。(文章是個人的理解,有哪里解釋的不正確請指正)