C語言實現(xiàn)定義字符串(雞肋)
眾所周知,在 C 語言中是沒有字符串類型的,今天 up 主為大家提供一種思路,也是為了保住自己即將掉落的秀發(fā)而作的一丁點努力。
字符概念
在計算機(jī)中,所有的數(shù)據(jù)都是由 0 與 1 組成的,0 與 1 向上建造了指令與數(shù)據(jù),字符是萬千個 0 與 1 映射的數(shù)據(jù)。計算機(jī)的硬件中流淌著除了指令就是數(shù)據(jù)這兩種類型,指令所作的工作就是搬運(yùn)數(shù)據(jù),然后交由 CPU 或者其他處理器處理數(shù)據(jù),最后將數(shù)據(jù)輸出到人們的感官中,供人們學(xué)習(xí)、工作、娛樂;
在 ASCII (美國信息交換標(biāo)準(zhǔn)代碼) 中,定義了一組字符映射表,使用十進(jìn)制的?0~127?,也就是 7 位( bit )?代表了包含,控制字符,數(shù)字( 0~9 ),小寫字母,大寫字母在內(nèi)的鍵盤上絕大多數(shù)字符。通俗的來說,ASCII 字符集,就是使用數(shù)字代表字符。以下是表的一部分:

于是我們得到:
其中 demo 變量就儲存著字符 'a'
查看輸出:
不同的字符集有著不同儲存規(guī)則,具體看其實現(xiàn)。
字符串
字符串,顧名思義,由多個字符按照順序串成一條,通常意義上來說其結(jié)尾包含 \0 字符。在 C 中使用 char * 定義字符串,如定義一個常量字符串,char *demo1 = "hello world"; 字符串存儲在常量區(qū),其結(jié)尾自動的被添加了 \0 字符,并無法更改字符串中的任何一個字符,使用?char demo[]?= "hello world"; 效果是一樣的,如果想要使用可改變的字符串(字符數(shù)組),那么需要提前得知字符串的長度,字符串又不會開口說話,然后告訴我們它的長度,那么怎么辦?有一種雞肋的辦法,那將上面兩種定義產(chǎn)生的字符串,復(fù)制到棧上來。
實現(xiàn)原理
定義一個字符串,等待被復(fù)制,獲取被復(fù)制字符串的長度,分配該長度的內(nèi)存空間,將字符串復(fù)制到分配的空間中,最后將字符數(shù)組地址賦值給新的字符指針中。這樣雞肋的行為,我只能一個字,絕!
我們先用語句實現(xiàn):
需要使用到的頭文件
在全局區(qū)定義 string 類型
在全局區(qū)定義臨時字符指針
定義過渡宏 _Dest_TEMP
在main函數(shù)中實現(xiàn)
第二行中,值依次從右往左進(jìn)行傳遞。alloca為gcc 內(nèi)置函數(shù),功能是在棧上分配內(nèi)存。
最后的 _Dest_TEMP = NULL;將中間變量初始化,防止誤用。
接下來輸出 demo變量,然后改變demo[1]的字符,我們在來看看是否被改變。
結(jié)果表明,字符串可以被改變
代碼全貌
我們將優(yōu)化以下代碼,將碎片整理到 stack.h 頭文件中
使用的時候,包含 stack.h 頭文件,并且在全局區(qū)定義?_Dest_TEMP_GLOBAL 即可,string _Dest_TEMP_GLOBAL = ((void *)0);?
舉例
至此,可以愉快的使用 stack 宏在棧上定義字符串了。
雞肋的地方
浪費(fèi)了內(nèi)存空間,這種做法會產(chǎn)生兩個相同的字符串;占用變量名,變量_Dest_TEMP_GLOBAL 不能再被定義,也不能被其他語句使用;需要 gcc 支持 alloca 內(nèi)置函數(shù),up 使用的兩個gcc 版本都支持:8.5、12.1.0;對于特定的平臺可能行不通,因為硬件上的內(nèi)存是有限的,或者某些平臺可能對棧設(shè)置了固定大小。