我不明白的预处理器宏

发布于 2024-09-01 06:54:51 字数 1135 浏览 5 评论 0原文

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

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;

这只是一个摘录,概述了我遇到的问题。整个内容可以在这里找到< /a>

I'm currently looking through some source code I found on the net, which makes use of preprocessor macros in a way I don't understand. It implements the quad-edge data-structure.
Hope that someone can clarify things for me!

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

and this is how they are used:

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;

This is just an excerpt to outline what I'm having problems with. The whole thing can be found here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

彻夜缠绵 2024-09-08 06:54:51

0xfffffffcu 只是一个无符号常量,除了最后 2 位为 0 外,所有位均设置为 1,即 11111111111111111111111111111100。它被用作掩码来操作 e 的底部两位。这些宏的全部意义似乎在于,您可以使用 4 个结构体的数组,将其视为循环数组(即模 4 索引)。

0xfffffffcu is just an unsigned constant with all bits set to 1 except the last 2 bits which are 0, i.e. 11111111111111111111111111111100. It's being used as a mask to maninpulate the bottom two bits of e. The whole point of these macros seems to be so that you can work with an array of 4 structs which you treat as a circular array (i.e. modulo 4 indexing).

情话已封尘 2024-09-08 06:54:51

这些宏只是简单的代码替换。至于他们在做什么则是另一回事了。

ONEXT(e) = e;

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

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

不要被宏淹没。只需用代码替换宏并弄清楚它的作用即可。之后重写它并添加一些评论,这样下一个人就不必经历你现在的情况。

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.

街角卖回忆 2024-09-08 06:54:51

等一下...

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,使用时不检查 NULL 并用无符号 int 进行掩码...

我不知道这段代码的用途,但我强烈建议不得将其用于任何目的

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.

£噩梦荏苒 2024-09-08 06:54:51

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

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

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

文件位于:聪明,但 euurrgghh (与 XOR 列表 一起)。

They are assuming that the malloc function is returning memory address aligned to at least four bytes. Since they assume that all memory allocations will result in a value with the lower two bits set to zero, they are using these two bits to store information. So, to get the data in the structure they need to clear these two bits to get the true address:

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

So, an edge_ref is a pointer to an object of type edge_struct and an index into the object's internal array (the (e)&3u bit).

File under: clever, but euurrgghh (alongside the XOR list).

浪漫之都 2024-09-08 06:54:51

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

My guess is that they have added tags to pointers, assuming they are aligned. (That's why there is masking operations before dereferencing).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文