1

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

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;

这只是概述我遇到的问题的摘录。整个事情可以在这里找到

4

5 回答 5

2

These macros are just a simple code substitution. As to what there are doing is another thing.

ONEXT(e) = e;

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

Which looks to me like they are loading a structure with data that is related to the address.

Don't get overwhelmed with the macros. Just substitute the code in for the macros and figure out what it does. After that re-write it and add some comments so the next person doesn't have to go through what you are now.

于 2010-05-12T15:34:17.110 回答
1

0xfffffffcu只是一个无符号常量,除了最后 2 位为 0 外,所有位都设置为 1,即11111111111111111111111111111100. 它被用作操纵e. 这些宏的重点似乎是让您可以处理一个由 4 个结构组成的数组,您将其视为一个循环数组(即模 4 索引)。

于 2010-05-12T15:32:54.507 回答
1

Wait a moment...

typedef int edge_ref;

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

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

The return of malloc is casted to a signed int, which is used without a check for NULL and masked with an unsigned int...

I don't know what this code is for, but I strongly recommend to not use it for any purpose.

于 2010-05-12T15:35:12.083 回答
1

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

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

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

归档在:聪明,但 euurrgghh (与XOR 列表一起)。

于 2010-05-12T15:39:38.423 回答
0

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

于 2010-05-12T15:38:39.940 回答