简体   繁体   English

我不明白的预处理器宏

[英]Preprocessor macros I don't understand

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 整个东西可以在这里找到

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; 变成((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. 之后,将其重新编写并添加一些注释,以便下一个人不必经历您现在的情况。

0xfffffffcu is just an unsigned constant with all bits set to 1 except the last 2 bits which are 0, ie 11111111111111111111111111111100 . 0xfffffffcu只是一个无符号常量,所有位都设置为1,最后2位为0,即11111111111111111111111111111100 It's being used as a mask to maninpulate the bottom two bits of e . 它被用作屏蔽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 (ie modulo 4 indexing). 这些宏的全部要点是,以便您可以使用包含4个结构的数组,将它们视为圆形数组(即,模4索引)。

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... malloc的返回被强制转换为一个有符号的int,该int无需检查NULL就可以使用,并由一个无符号的int来掩盖...

I don't know what this code is for, but I strongly recommend to not use it for any purpose. 我不知道此代码的用途,但我强烈建议不要将其用于任何目的。

They are assuming that the malloc function is returning memory address aligned to at least four bytes. 他们假设malloc函数正在返回至少与四个字节对齐的内存地址。 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). 因此,edge_ref是指向edge_struct类型的对象的指针,并且是该对象的内部数组的索引((e)&3u位)。

File under: clever, but euurrgghh (alongside the XOR list ). 归档于:聪明,但是euurrgghh(与XOR列表一起)。

My guess is that they have added tags to pointers, assuming they are aligned. 我的猜测是,假设它们是对齐的,它们已经向指针添加了标签。 (That's why there is masking operations before dereferencing). (这就是为什么在取消引用之前进行屏蔽操作的原因)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM