C語(yǔ)言5 -字符和字符串

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

image

字符類(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

image

觀察ASCII表中并沒(méi)有中文字符

拓展 ASCII碼表 (EASCII)

詳見(jiàn) 維基百科 https://zh.wikipedia.org/wiki/EASCII

image

如何在計(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

  1. 兩種編碼可能使用相同的數(shù)字代表兩個(gè)不同的符號(hào)
  2. 或者使用相同的數(shù)字代表不同的符號(hào)

這種編碼方式有很大的弊端,當(dāng)試用此種編碼方式的數(shù)據(jù),在其他國(guó)家使用的時(shí)候,如果其他國(guó)家使用類(lèi)似的編碼規(guī)則,那么數(shù)據(jù)就會(huì)失去原本的意義。

Unicode編碼就是為了解決這個(gè)問(wèn)題才出現(xiàn)的!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容