2012-09-03 25 views
10

以下の構造体の定義では、マクロ定義(#define)の行があります。その行は何を正確にしていますか?私はそれが配列h_addr_listの最初のエントリにエイリアスを作成することを理解しますが、それはまだ私に奇妙に見えます。 h_addrhostentのメンバーですか?この定義は構造体のスコープ内でのみですか?構造体定義のマクロを定義しています

struct hostent 
{ 
    char *h_name;  /* official name of host */ 
    char **h_aliases; /* alias list */ 
    int  h_addrtype;  /* host address type */ 
    int  h_length;  /* length of address */ 
    char **h_addr_list; /* list of addresses from name server */ 
    #define h_addr h_addr_list[0] /* address, for backward compatiblity */ 
}; 

答えて

16

マクロ定義のスコープがまったく設定されていない場合、マクロ定義はその構造体の外側に定義されていれば同じ方法で動作します。

he.h_addr_list[0]hestruct hostentであることを前提とします)に変更するのではなく、古いコードをhr.h_addrのまま使用することができます。

h_addrは、struct hostentのフィールドではありません。その定義はプリプロセッサによって処理され、実際のコンパイラには#defineがある空の行が表示されます。
コードがhe.h_addrと書かれている場合、プリプロセッサはそれを修正してhe.h_addr_list[0]に置き換えます。これが実際のコンパイラに見られます。

プリプロセッサのマクロはスコープされることはありません。コンパイラ本体はそれらを参照しません。置換の結果のみを表示し、プリプロセッサは完全にスコープを無視します。

+0

私はあなたの回答を部分的にしか理解していません。例えば、 'h_addr'が' struct hostent'のメンバである場合、それが単なるマクロである場合、なぜですか? – pap42

+2

'h_addr'は' struct hostent'のフィールドではありません。その定義はプリプロセッサによって処理され、実際のコンパイラは '#define'がある空行を見ます。しかし、あるコードが 'he.h_addr'と書かれていると、プリプロセッサはそれを修正し、' he.h_addr_list [0] 'と置き換えます。これが実際のコンパイラに見られます。 – Mat

+0

あなたの返答は素晴らしいですが、将来の読者のために(ちょうどあなたが作成したコメントを含むかもしれませんか? – pap42

5

定義されると、マクロ識別子はCのスコープ規則とは関係なく表示されたままになります。その範囲は、翻訳単位の終わりまたは対応する#undefの指示が出るまで、その定義から始まります。

ここでは、構造内の定義は読みやすくするためのものです。構造の後にマクロを定義することもできます。

struct hostent 
{ 
    char *h_name; 
    char **h_aliases; 
    int h_addrtype; 
    int h_length; 
    char **h_addr_list; 
}; 

#define h_addr h_addr_list[0] 

これはフィールドではありません。ユーザーはs.h_addr_list[0]の代わりにs.h_addrと書くことができます。

0

マクロ定義のスコープが設定されていないため、このマクロはこの定義を参照するコンパイル単位内で表示され、undef h_addrまで表示されます。

関連する問題