2013-02-26 105 views
0

這個問題通常更多的是概念性問題,而不是本質上的編碼問題。我很奇怪,因爲我遇到了這些代碼片段,並想知道它們是否有效。或者爲什麼基本上,如果有人可以給我一個解釋,請?C中的類型聲明(概念)

這裏有一些C類型聲明:

typedef struct Rec1 * Ptr1; 
typedef struct Rec2 * Ptr2; 

struct Rec1 
{ 
    int data; 
    Ptr2 next; 
}; 

struct Rec2 
{ 
    double data; 
    Ptr2 next; 
}; 

如果這些被允許?他們被允許嗎?爲什麼或者爲什麼不?

+3

是的,這段代碼是有效的。你有什麼特別的問題? – 2013-02-26 02:34:36

+0

你的問題到底是什麼?你想要解釋什麼?你發佈了一些有效的代碼,一個相當基本的代碼,並問爲什麼它是有效的......這就像問爲什麼2 + 2是4.如何回答這樣的問題?你在這段代碼中看到的是什麼引起了你的注意? – AnT 2013-02-26 02:52:13

+0

@AndreyT - 我在一本書中讀過這段代碼,並沒有說它是否有效。我最近了解了結構和他們可以申報的方式,所以我想我會把這個問題提交給社區,看看有什麼解釋! – thestralFeather7 2013-02-26 03:12:41

回答

3

它們是否有效?

是它們是有效的

原因:

  1. 前兩行的struct Rec1 *struct Rec2 *創建Ptr1Ptr2作爲類型定義。

  2. 由於它們是指針,而不是結構本身,它們使struct Rec1struct Rec2作爲不完全類型,並且它們只是使Rec2遞歸類型(通常在創建數據結構使用)和Rec1作爲具有指針Rec2對象。

他們應該允許嗎?

你還可以如何創建自引用結構?

+0

我不明白第2點.typedefs *是*聲明結構類型爲不完整的。 – Pubby 2013-02-26 02:43:22

+0

@Pubby謝謝你,你是對的,糾正它 – 2013-02-26 02:45:40

+0

它似乎仍然不正確。行'typedef struct Rec1 * Ptr1;'聲明瞭一個不完整的結構類型:'Rect1',以及一個完整的指針類型:'Ptr1'。 「Ptr1」是一個指針的事實不會改變「Rec1」的聲明。 – Pubby 2013-02-26 02:53:06

1

短的版本:

  • 它應該被允許?是

  • 他們是否(正向類型定義)?是。

  • 爲什麼或爲什麼不?

這是一種普遍接受的前向型聲明方式。它允許聲明一個不完整的類型並在稍後定義它。在這種簡單的情況下這不是什麼大問題,但在更復雜的情況下可能是絕對必要的。

Linux或Darwin內核都相當廣泛地使用這種技術來聲明內部內核結構,允許在其自己的頭文件中定義數據類型,但允許在完全定義數據類型之前使用它。

沒有這種機制,複雜的,相互依賴的數據類型定義將是不可能的。

0

typedef只是它引用的實際類型的別名。你可以把它看作一個宏,但它不是在編譯的預處理階段被替換的東西。

只是代的所有出現PTR1結構REC 1 *產生一個有效的代碼,這是確認代碼是否有效的最簡單的方法;)

1

根據語言標準,它們是有效的因此應該被允許。

現在,如果你問這一切如何工作,這很容易。

指針通常只是內存地址。如果對象由整數個字節表示(每個字節都有一個唯一的地址),則可以有一個指向內存中任何對象的指針。我在這裏說「整數」,因爲你不能有一個指向結構位域的指針(至少,你不能有一個指向那些不在字節邊界上開始並佔用整數個字節的指針) 。

因此,Ptr2只是一個事先已知大小的指針類型(如果您的CPU的地址空間是從0到4 GB,則32位地址足以尋址每個字節,32位將是本機指針大小)這個CPU),並且您可以爲struct Rec1struct Rec2中的這樣一個指針分配空間,即使這個指針指向的內容還不知道,這就是我們在代碼中遇到的問題。 Ptr1Ptr2被定義爲不完整的類型,這是這個的正式名稱。

在語言中實現這種不完整指針類型的基本原理非常實用。如果你想創建鏈表或樹,它們的元素或節點必須以某種方式指向其鏈接的其他元素或節點。理論上,您可以爲最後一個元素(或葉節點)創建不同的元素/節點類型,然後爲指向它的那個創建不同的元素/節點類型,然後爲指向該元素的元素/節點類型創建一個,依此類推。但是,如果你不僅僅只有少數幾個元素或者節點,那麼這並不能很好地擴展。如果你想要一百萬呢?確定一百萬個幾乎相同的類型是不切實際的。所以,該語言爲您提供了一條捷徑,以避免這種情況。您也可以將next指針指定爲void*指針,但是隨後您需要將它們全部投射到struct Rect1*struct Rect2*,並且維護和調試此類代碼時容易出錯。所以,在那裏,語言給你一個手。

+0

您能否解釋'typedef struct Rec2 * Ptr2'結束的好處,就像在'struct'定義中說的'struct Rec2 * next'一樣?有沒有好處?我還沒有看到它。 – d0rmLife 2013-02-26 03:37:40

+0

@ d0rmLife當你需要一個''Ptr2'的輸入比'struct Rec2 *'少? – 2013-02-26 03:58:35

+0

大聲笑。德勤。在我已閱讀過的關於這種數據結構的材料中,公約將按照上面的評論聲明它們。所以我想知道是否有這樣的'typedef'聲明給出了一些功能 - 除了緊湊性外,我想......! – d0rmLife 2013-02-26 04:04:01