2014-03-12 56 views
1

我有我要转换为宏而不违反类型安全转换一个行函数宏在C

#define UINTPTR_MAX_XOR_WITH_1 (uintptr_t) (UINTPTR_MAX^1) 
struct node 
{ 
    unsigned long key; 
    tbb::atomic<struct node*> lChild; //format <address,flagBit> 
    tbb::atomic<struct node*> rChild; //format <address,flagBit> 
}; 

struct node* getAddress(struct node* p) 
{ 
    return (struct node*)((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1); 
} 

main() 
{ 
    nodeAddr = getAddress(node); 
    lNodeAddr = getAddress(node->lChild); 
} 

我尝试用这个宏替换getAddress()功能的功能。我知道这个宏定义是错误的。

#define getAddress(p) ((struct node*) (uintptr_t) p & UINTPTR_MAX_XOR_WITH_1) 

我看到这篇文章 Macro vs Function in C 但还是没能弄清楚如何做到这一点对于这种情况

+0

该函数肯定比宏好。而你的主要是相当时髦。 –

+0

为什么认为这个函数比一个宏好。主要更复杂。我只是把相关的代码放在这里:) – arunmoezhi

+0

宏通常更糟。你为什么喜欢他们? –

回答

1

这几乎是等价的,不过宏比功能更宽容时类型检查它的参数:

#define getAddress(p) ((struct node*) ((uintptr_t) (struct node*)(p) & UINTPTR_MAX_XOR_WITH_1)) 

一些C编译器接受static inline,这不是一个宏,但它等同于原有的功能,并且将获得内联大部分时间在实践中:

static inline struct node* getAddress(struct node* p) { 
    return (struct node*)((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1); 
} 
+0

谢谢。它工作完美。我在启用'-O3'标志的情况下使用'gcc'。由于这是一个单行函数,我预计它在编译期间会被内联 – arunmoezhi

+0

_double_ cast对'p'做了什么? –

+0

@JosephQuinsey:我认为你是对的。 '(uintptr_t)(p)'会很好。由于'p'是'struct node *'的类型,因此再次对它进行类型转换是多余的 – arunmoezhi