簡體   English   中英

我不明白的預處理器宏

[英]Preprocessor macros I don't understand

我目前正在瀏覽在網上找到的一些源代碼,這些源代碼以我不了解的方式利用了預處理器宏。 它實現了四邊緣數據結構。 希望有人可以幫我澄清一下!

typedef int edge_ref;

typedef struct {
    edge_ref next[4];
    void *data[4];
    unsigned mark;
} edge_struct;

#define ROT(e) (((e)&0xfffffffcu)+(((e)+1)&3u))
#define SYM(e) (((e)&0xfffffffcu)+(((e)+2)&3u))
#define TOR(e) (((e)&0xfffffffcu)+(((e)+3)&3u))

#define ONEXT(e) ((edge_struct *)((e)&0xfffffffcu))->next[(e)&3]
#define ROTRNEXT(e) ((edge_struct *)((e)&0xfffffffcu))->next[((e)+1)&3]
#define SYMDNEXT(e) ((edge_struct *)((e)&0xfffffffcu))->next[((e)+2)&3]
#define TORLNEXT(e) ((edge_struct *)((e)&0xfffffffcu))->next[((e)+3)&3]

#define MARK(e)  ((edge_struct *)((e)&0xfffffffcu))->mark

這是它們的用法:

edge_ref e;
e = (edge_ref) malloc(sizeof(edge_struct));
ONEXT(e) = e;
SYMDNEXT(e) = SYM(e);
ROTRNEXT(e) = TOR(e);
TORLNEXT(e) = ROT(e);
MARK(e) = 0;
return e;

這只是摘錄,概述了我遇到的問題。 整個東西可以在這里找到

這些宏只是簡單的代碼替換。 至於正在做什么是另一回事。

ONEXT(e) = e;

變成((edge_struct *)(((e)&0xfffffffcu))-> next [(e)&3] = e;

在我看來,這就像他們正在使用與地址相關的數據加載結構一樣。

不要對宏不知所措。 只需用代碼代替宏並弄清楚它的作用。 之后,將其重新編寫並添加一些注釋,以便下一個人不必經歷您現在的情況。

0xfffffffcu只是一個無符號常量,所有位都設置為1,最后2位為0,即11111111111111111111111111111100 它被用作屏蔽e兩位。 這些宏的全部要點是,以便您可以使用包含4個結構的數組,將它們視為圓形數組(即,模4索引)。

稍等片刻...

typedef int edge_ref;

#define ONEXT(e) ((edge_struct *)((e)&0xfffffffcu))->next[(e)&3]

e = (edge_ref) malloc(sizeof(edge_struct));
ONEXT(e) = e;

malloc的返回被強制轉換為一個有符號的int,該int無需檢查NULL就可以使用,並由一個無符號的int來掩蓋...

我不知道此代碼的用途,但我強烈建議不要將其用於任何目的。

他們假設malloc函數正在返回至少與四個字節對齊的內存地址。 由於他們假定所有內存分配都會導致將低兩位設置為零的值,因此他們正在使用這兩位存儲信息。 因此,要獲取結構中的數據,他們需要清除這兩位以獲取真實地址:

((edge_struct *)((e)&0xfffffffcu))

因此,edge_ref是指向edge_struct類型的對象的指針,並且是該對象的內部數組的索引((e)&3u位)。

歸檔於:聰明,但是euurrgghh(與XOR列表一起)。

我的猜測是,假設它們是對齊的,它們已經向指針添加了標簽。 (這就是為什么在取消引用之前進行屏蔽操作的原因)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM