繁体   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