C語(yǔ)言5 -字符和字符串
int x = 123; //補(bǔ)碼
int float f = 123.4F; //IEEE編碼
int i = 'A'; //神馬情況???
我們?cè)诖a中寫(xiě)入
int i = 'A';
反編譯后匯編就編程了
mov dword ptr ss:[esp-4],0x41
為什么會(huì)變成41呢?
字符類(lèi)型
ASCII 表
(American Standard Code for Information Interchange 美國(guó)標(biāo)準(zhǔn)信息交換代碼)
維基百科: https://zh.wikipedia.org/wiki/ASCII

字符類(lèi)型
ASCII表最大 127 16進(jìn)制 是 0x7F 也就是只需要一個(gè)字節(jié)
一個(gè)字節(jié)就夠了,所以通常我們會(huì)使用:
char x ='A'來(lái)存這種符號(hào)
所以,很多書(shū)會(huì)稱(chēng)char為字符類(lèi)型。
其實(shí)這種說(shuō)法是錯(cuò)誤的,會(huì)讓很多初學(xué)者認(rèn)為char就是用來(lái)存儲(chǔ)字符的
轉(zhuǎn)義字符
比如換行符可以寫(xiě)為
char i = '\n';
或者
char i = 10;
C語(yǔ)言中的內(nèi)置函數(shù)
putchar(10); // 將對(duì)應(yīng)數(shù)從ASCII表中查出畫(huà)在(打印) 控制臺(tái)上(一次只能打印一個(gè)字符)
putchar('\n');
printf函數(shù)的使用
#include <stdio.h>
void main()
{
printf("Hello World!\n"); //打印字符串
int x = 0xFFFFFFFF;
printf("%d %u %x\n",x,x,x); //打印證書(shū)
//-1 4294967295 ffffffff
float f = 3.1415F;
printf("%6.2f\n",f); //打印浮點(diǎn)數(shù)
//3.14
}
占位符:
%d 有符號(hào)數(shù)形式打印
%u 無(wú)符號(hào)形式打印
%x 16進(jìn)制形式打印
%{x.y}f 打印浮點(diǎn)數(shù) x標(biāo)志打印總長(zhǎng)度 y 代表小數(shù)點(diǎn)后長(zhǎng)度
字符串 一堆字符的ASCII對(duì)應(yīng)的的值在內(nèi)存中連續(xù)的串
printf函數(shù)調(diào)用前 push 字符串在內(nèi)存中保存的位置
vc6 反匯編:
push offset string "Hello World!" (0042f6c)
call printf(0040d3f0)
add esp,4
字符串的結(jié)束標(biāo)志在內(nèi)存中 是 00
出現(xiàn)00代表字符串結(jié)束
字符串
char buffer[20] = "Hello World!";
printf("%s\n",buffer);
%s 字符串形式打印
中文字符
char buffer[20]= "Hello World!";
printf("%s\n",buffer);
反匯編代碼
5: char buffer[20]= "Hello World!";
00401028 A1 20 00 42 00 mov eax,[string "Hello World!" (00420020)]
0040102D 89 45 EC mov dword ptr [ebp-14h],eax
00401030 8B 0D 24 00 42 00 mov ecx,dword ptr [string "Hello World!"+4 (00420024)]
00401036 89 4D F0 mov dword ptr [ebp-10h],ecx
00401039 8B 15 28 00 42 00 mov edx,dword ptr [string "Hello World!"+8 (00420028)]
0040103F 89 55 F4 mov dword ptr [ebp-0Ch],edx
00401042 A0 2C 00 42 00 mov al,[string "Hello World!"+0Ch (0042002c)]
00401047 88 45 F8 mov byte ptr [ebp-8],al
0040104A 33 C9 xor ecx,ecx
0040104C 89 4D F9 mov dword ptr [ebp-7],ecx
0040104F 66 89 4D FD mov word ptr [ebp-3],cx
00401053 88 4D FF mov byte ptr [ebp-1],cl
6: printf("%s\n",buffer);
00401056 8D 55 EC lea edx,[ebp-14h]
00401059 52 push edx
0040105A 68 1C 00 42 00 push offset string "%s\n" (0042001c)
0040105F E8 3C 00 00 00 call printf (004010a0)
00401064 83 C4 08 add esp,8
中文
char buffer[20] = "中國(guó)";
printf("%s\n",buffer);
反匯編
5: char buffer[20] = "中國(guó)";
00401028 A1 20 00 42 00 mov eax,[string "\xd6\xd0\xb9\xfa" (00420020)]
0040102D 89 45 EC mov dword ptr [ebp-14h],eax
00401030 8A 0D 24 00 42 00 mov cl,byte ptr [string "Hello World!"+4 (00420024)]
00401036 88 4D F0 mov byte ptr [ebp-10h],cl
00401039 33 D2 xor edx,edx
0040103B 89 55 F1 mov dword ptr [ebp-0Fh],edx
0040103E 89 55 F5 mov dword ptr [ebp-0Bh],edx
00401041 89 55 F9 mov dword ptr [ebp-7],edx
00401044 66 89 55 FD mov word ptr [ebp-3],dx
00401048 88 55 FF mov byte ptr [ebp-1],dl
6: printf("%s\n",buffer);
0040104B 8D 45 EC lea eax,[ebp-14h]
0040104E 50 push eax
0040104F 68 1C 00 42 00 push offset string "%s\n" (0042001c)
00401054 E8 47 00 00 00 call printf (004010a0)
00401059 83 C4 08 add esp,8

觀察ASCII表中并沒(méi)有中文字符
拓展 ASCII碼表 (EASCII)
詳見(jiàn) 維基百科 https://zh.wikipedia.org/wiki/EASCII

如何在計(jì)算機(jī)中存儲(chǔ)中文
我們發(fā)現(xiàn)就算加上 EASCII 也不能表示中文 于是我們?nèi)绾卧谟?jì)算機(jī)中存儲(chǔ)中文呢?
計(jì)算機(jī)發(fā)明之后及后面很長(zhǎng)一段時(shí)間,只能應(yīng)用于美國(guó)及西方一些發(fā)達(dá)國(guó)家,ASCII能夠很好滿(mǎn)足用戶(hù)的需求。但是當(dāng)天朝也有了計(jì)算機(jī)之后,為了顯示中文。必須設(shè)計(jì)一套編碼規(guī)則用于漢字轉(zhuǎn)換為計(jì)算機(jī)可以接受的數(shù)字系統(tǒng)的數(shù)
天朝專(zhuān)家把那些127號(hào)后的奇異符號(hào)們 (即EASCII)取消掉,規(guī)定:一個(gè)小于127的字符意義與原來(lái)相同,但是兩個(gè)大于127的字符連在一起時(shí),就表示一個(gè)漢字,這樣我們就可以組合出大約7000多個(gè)簡(jiǎn)體漢字了
在這些編碼里,連在ASCII里本來(lái)就有的數(shù)字、標(biāo)點(diǎn)、字母都統(tǒng)統(tǒng)編了兩個(gè)字節(jié)長(zhǎng)的編碼,這就是常說(shuō)的”全角“字符,而原來(lái)在127號(hào)以下的那些就叫”半角“字符了。
上述編碼規(guī)則就是GB2312或GB2312-80
GB2312或GB2312-80
- 兩種編碼可能使用相同的數(shù)字代表兩個(gè)不同的符號(hào)
- 或者使用相同的數(shù)字代表不同的符號(hào)
這種編碼方式有很大的弊端,當(dāng)試用此種編碼方式的數(shù)據(jù),在其他國(guó)家使用的時(shí)候,如果其他國(guó)家使用類(lèi)似的編碼規(guī)則,那么數(shù)據(jù)就會(huì)失去原本的意義。
Unicode編碼就是為了解決這個(gè)問(wèn)題才出現(xiàn)的!