495 - 第二章 結(jié)構(gòu)污茵、聯(lián)合和枚舉 41-50

495 - 第二章 結(jié)構(gòu)、聯(lián)合和枚舉 41-50

結(jié)構(gòu)葬项、聯(lián)合和枚舉的相似點是可以定義新的類型泞当,首先,通過聲明結(jié)構(gòu)和聯(lián)合的成員或域或者構(gòu)成枚舉的常量來定義新的類型民珍。同時襟士,也可能需要給新類型賦一個標(biāo)簽(tag),以便在以后引用嚷量。定義新的類型之后陋桂,就可以立即或者稍后(通過使用標(biāo)簽)來聲明這個類型的實例了

更麻煩的事,也可以使用typedef來為用戶定義類型定義新的類型名稱蝶溶,如對其他任何類型一樣嗜历。但是,如果這樣做抖所,必須意識到類型定義名稱和標(biāo)簽名沒有任何關(guān)系

41 下面這兩個聲明有什么不同

struct x1 {...};
typedef struct {...} x2;

答:第一種形式聲明聲明了一個“結(jié)構(gòu)標(biāo)簽”梨州;第二種聲明了一個“類型定義”。主要區(qū)別在于第二種聲明更抽象以下--用戶不必知道它是一個結(jié)構(gòu)田轧,并且在聲明它的實例事也不需要使用struct關(guān)鍵字.

x2 b;

但使用標(biāo)簽聲明的結(jié)構(gòu)就必須用這樣的形式進(jìn)行定義

struct x1 a;
//(也可以同時使用兩種方法:
typedef struct x3 {...} x3;
//盡管有些晦澀暴匠,但為標(biāo)簽和類型定義使用同樣的名稱是合法的,因為它們處于獨立的命名空間中

42.這樣的代碼對不對

strcut x {...};
x thestruct;

答:C不是C++傻粘。不能用結(jié)構(gòu)標(biāo)簽自動生成類型定義名每窖。事實上,C語言中的結(jié)構(gòu)是這樣用關(guān)鍵字struct聲明的:

struct x thestruct;

如果你愿意弦悉,也可以在聲明結(jié)構(gòu)的時候聲明一個類型定義窒典,然后再用類型定義名稱去聲明真正的結(jié)構(gòu);

typedef struct {...} tx;
tx thestruct;

43.結(jié)構(gòu)可以包含自己的指針嗎稽莉?

答:當(dāng)然可以崇败,但如果你要使用typedef,則有可能產(chǎn)生問題。

44.在C語言中使用什么方法實現(xiàn)抽象數(shù)據(jù)類型最好后室?

答:讓客戶使用指向沒有公開定義(也許還隱藏在類型定義后邊)的結(jié)構(gòu)類型的指針是一個好辦法缩膝。換而言之,客戶使用結(jié)構(gòu)指針(及調(diào)用輸入和返回結(jié)構(gòu)指針的函數(shù))而不知道結(jié)構(gòu)的成員是什么岸霹,只要不需要結(jié)構(gòu)的細(xì)節(jié)--也就是說疾层,只要不使用->\sizeof\操作符幾真是的結(jié)構(gòu)聲明--C語言事實上可以正確處理不完全類型的結(jié)構(gòu)指針。只有在實現(xiàn)抽象數(shù)據(jù)類型的源文件中才需要次范圍內(nèi)的結(jié)構(gòu)的完整聲明

45贡避。在C語言中是否有模擬繼承等面向?qū)ο蟪绦蛟O(shè)計特性的好方法痛黎?

答:把函數(shù)指針直接加入到結(jié)構(gòu)中就可以實現(xiàn)簡單的“方法”。你可以使用各種不雅而暴力的方法來實現(xiàn)繼承刮吧,例如通過預(yù)處理機(jī)或讓“基類”的結(jié)構(gòu)作為初始的子集湖饱,但這些方法都不完美。很明顯杀捻,也沒有操作符的重載和覆蓋(例如井厌,“派生類”中的“方法”,那些必須人工去左)致讥。

47.我遇到這樣聲明結(jié)構(gòu)的代碼

struct name
{
    int name[];
    char namestr[1];
};

然后又使用一些內(nèi)存分配技巧事namestr數(shù)組用起來好像有多個元素仅仆,namelen記錄了元素的個數(shù),它是怎樣工作的垢袱?這樣事合法的可移植的嗎墓拜?

答:不清楚這樣做是否合法或者可移植。但這種技術(shù)十分普遍请契。這種技術(shù)的某種實現(xiàn)可能像這個樣子:

#include <stdlib.h>
#include <string.h>
struct name *makename (char *newname) {
    struct name *ret = malloc(sizeof(struct name) - 1 + strlen(newname) + 1);
    if(ret != NULL) {
        ret->namelen = strlen(newname);
        strcpy(ret->namestr, newname);
    }
    return ret;
}

這個函數(shù)分配了一個name結(jié)構(gòu)的實例并調(diào)整它的大小咳榜,以便將請求的名稱(不是結(jié)構(gòu)聲明所示的僅僅一個字符)置入namestr域中。

雖然很流行爽锥,但這種技術(shù)也在某種程度上惹人非議贿衍。Dennis Ritchie就稱之為“和C實現(xiàn)的無保證的親密接觸”,官方的解釋認(rèn)定他沒有嚴(yán)格遵守C語言標(biāo)準(zhǔn)救恨。(關(guān)于這種技術(shù)的合法性的完整討論超出了本書的范圍),這種技術(shù)也不能保證在所有的實現(xiàn)上是可移植的释树,(仔細(xì)檢查數(shù)組邊界的編譯器可能會發(fā)出警告)肠槽。

另一種可能是吧變長的元素聲明成很大,而不是很小奢啥。上面的例子可以這樣改寫:

#include <stdlib.h>
#include <string.h>
struct name
{
    int nemalen;
    char namestr[MAX];
};

struct name *makename (char *newname)
{
    struct name *ret = malloc(sizeof(struct name) - MAX +strlen(newname) + 1);

    if(ret !=NULL) {
        ret->namelen = strlen(newname);
        strcpy(ret->namestr, newname);
    }
    return ret;
}

當(dāng)然秸仙,此處的MAX應(yīng)該比任何可能存儲的名字長度都打。但是桩盲,這種技術(shù)似乎也不完全符合標(biāo)準(zhǔn)的嚴(yán)格解釋:

當(dāng)然寂纪,真正安全的正確的做法是使用字符指針,而不是數(shù)組

#include <stdlib.h>
#include <string.h>
struct name
{
    int nemalen;
    char *namep;
};
struct name *makename (char *newname)
{
    struct name *ret = malloc(sizeof(struct name));

    if(ret !=NULL) {
        ret->namelen = strlen(newname);
        ret->namep = malloc(ret->namelen + 1);
        if(ret->namep ==NULL) {
            free(ret);
            return NULL;
        }
        strcpy(ret->namestr, newname);
    }
    return ret;
}

顯然,把長度和字符串保存在同一塊內(nèi)存中的“方便”已經(jīng)不復(fù)存在了捞蛋,而且在釋放這個結(jié)構(gòu)的實例的時候需要兩次調(diào)用free孝冒。

如果像上面的例子那樣,存儲的數(shù)據(jù)類型是字符拟杉,那么為保持連續(xù)性庄涡,可以直截了當(dāng)?shù)膶纱蝝alloc調(diào)用合成一次,(這樣也可以只用一次調(diào)用free就能釋放)搬设。

struct name makename(char *newname)
{
    char *buf = malloc((struct name) + strlen(newname) +1);
    struct name *ret = (struct name *)buf;
    ret->namelen = strlen(newname);
    ret->namep = buf + sizeof(struct name);
    strcpy(ret->namep, newname);

    return ret;
};

但是穴店,想這樣用一次malloc調(diào)用將第二個區(qū)域接上的技巧只有在第二個區(qū)域是char型數(shù)組的時候才可移植,對于任何大一些的類型拿穴,對齊變得十分重要泣洞,必須保持

49.為什么不能用內(nèi)建的==和!=操作符比較結(jié)構(gòu)默色?

答:沒有一個好的球凰,符合C語言的底層特性的方法讓編譯器來實現(xiàn)結(jié)構(gòu)比較。簡單的按字節(jié)比較的方法可能會在遇到結(jié)構(gòu)中沒有使用的“東 hole”的隨機(jī)內(nèi)容的時候失敗该窗。而安域比較在處理大結(jié)構(gòu)時可能需要難以接受的大量重復(fù)代碼弟蚀。任何編譯器生成的比較代碼都不能期望在所有情況下都能正確比較指針域。例如比較char * 域的時候一般都希望使用strcmp而不是==酗失;如果需要比較兩個結(jié)構(gòu)义钉,必須自己寫函數(shù)按域比較。

50.結(jié)構(gòu)傳遞和返回是如何實現(xiàn)的规肴?

答:當(dāng)結(jié)構(gòu)作為函數(shù)參數(shù)傳遞的時候捶闸,通常會把整個結(jié)構(gòu)都推進(jìn)棧,需要多少空間就使用多少空間拖刃。(正是為了避免這個代價删壮,程序員經(jīng)常使用指針而不是結(jié)構(gòu))。某些編譯器僅僅傳遞一個結(jié)構(gòu)的指針兑牡,但是為了保證按值傳遞的語義央碟,它們可能不得不保留一份局部fuben。

編譯器通常會提供一個額外的“隱藏”參數(shù)均函,用于指向函數(shù)返回的結(jié)構(gòu)亿虽,有些老式的編譯器使用一個特殊的靜態(tài)位置來返回結(jié)構(gòu),這回導(dǎo)致返回結(jié)構(gòu)的函數(shù)不可再入苞也,這是ANSIC所不允許的洛勉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市如迟,隨后出現(xiàn)的幾起案子收毫,更是在濱河造成了極大的恐慌攻走,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件此再,死亡現(xiàn)場離奇詭異昔搂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)引润,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進(jìn)店門巩趁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淳附,你說我怎么就攤上這事议慰。” “怎么了奴曙?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵别凹,是天一觀的道長。 經(jīng)常有香客問我洽糟,道長炉菲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任坤溃,我火速辦了婚禮拍霜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘薪介。我一直安慰自己祠饺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布汁政。 她就那樣靜靜地躺著道偷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪记劈。 梳的紋絲不亂的頭發(fā)上勺鸦,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天,我揣著相機(jī)與錄音目木,去河邊找鬼换途。 笑死,一個胖子當(dāng)著我的面吹牛刽射,可吹牛的內(nèi)容都是我干的军拟。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼柄冲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了忠蝗?” 一聲冷哼從身側(cè)響起现横,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戒祠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骇两,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年姜盈,在試婚紗的時候發(fā)現(xiàn)自己被綠了低千。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡馏颂,死狀恐怖示血,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情救拉,我是刑警寧澤难审,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站亿絮,受9級特大地震影響告喊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜派昧,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一黔姜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒂萎,春花似錦秆吵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至豺撑,卻和暖如春烈疚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聪轿。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工爷肝, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陆错。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓灯抛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親音瓷。 傳聞我的和親對象是個殘疾皇子对嚼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 在這個瞬息萬變的互聯(lián)網(wǎng)時代里纵竖,每個人都想做很多事情漠烧,掌握很多項技能,閱讀靡砌、寫作已脓、攝影、旅行通殃、烘焙……但是很多人只是...
    遇見0225閱讀 300評論 1 0
  • 新茶裝滿簍 新酒已開倉 新米鍋里煮 新郎娶新娘 好春光度液,正明亮 一聲燕啼柳葉香 好春光,雨微涼 鴨子悠哉暖春江 百...
    快樂流浪漢甲閱讀 86評論 2 2