预处理器宏我不明白

时间:2010-05-12 15:23:12

标签: c data-structures macros c-preprocessor binary-operators

我目前正在查看我在网上找到的一些源代码,它以我不理解的方式使用预处理器宏。它实现了四边数据结构。 希望有人能为我澄清一切!

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;

这只是一个摘录,概述了我遇到的问题。整个事情可以找到here

5 个答案:

答案 0 :(得分:2)

这些宏只是一个简单的代码替换。关于做什么是另一回事。

ONEXT(e) = e;

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

在我看来,他们正在加载一个包含与地址相关的数据的结构。

不要被宏淹没。只需将代码替换为宏,并找出它的作用。在那之后重新写它并添加一些评论,以便下一个人不必经历你现在的样子。

答案 1 :(得分:1)

0xfffffffcu只是一个无符号常量,除最后2位为0外,所有位都设置为1,即11111111111111111111111111111100。它被用作掩码,以便对e的底部两位进行操作。这些宏的重点似乎是你可以处理一个4个结构的数组,你将它们视为一个圆形数组(即模4索引)。

答案 2 :(得分:1)

等一下......

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的返回被转换为signed int,使用时不检查NULL并使用unsigned int进行掩码...

我不知道这段代码的用途,但我强烈建议不要用它用于任何目的。

答案 3 :(得分:1)

他们假设malloc函数返回的内存地址至少与四个字节对齐。由于它们假设所有存储器分配将导致低两位设置为零的值,因此它们使用这两位来存储信息。因此,为了获得结构中的数据,他们需要清除这两个位以获得真正的地址:

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

因此,edge_ref是指向edge_struct类型的对象的指针,以及对象内部数组的索引((e)& 3u位)。

文件在:聪明,但是euurrgghh(和XOR list一起)。

答案 4 :(得分:0)

我猜他们已经为指针添加了标签,假设它们是对齐的。 (这就是为什么在解除引用之前有掩蔽操作的原因。)