有什么技巧可以禁止将C宏称为左值吗?

| 例如,
struct node {
  struct node *left, *right;
};
#define LEFT(X) (X->left)
#define RIGHT(X) (X->right)
我想禁止这样的宏调用而不更改现有的宏接口。
LEFT(n) = ...
任何的想法?     
已邀请:
尝试这个:
#define LEFT(X) ((X)->left+0)
#define RIGHT(X) ((X)->right+0)
    
#undef LEFT
#undef RIGHT

//template<class T>
inline const node * const LEFT(const node * X) {
    return X->left;
}
    
我会使用内联函数,但是如果您想要一个宏:
#define LEFT(X) (1 ? (X)->left : 0)
    
我认为没有任何方法可以防止这种情况。最好的方法可能是不使用宏。     
您可以使用三元运算符将宏的结果强制为右值,但错误消息可能会使用户感到困惑:
struct node {
   node *left, *right;
};
#define LEFT( x ) ( true ? (x).left : (node*)0 )
int main() {
   node n;
   // LEFT( n ); // error
   node *l = LEFT( n ); // OK
}
那个特定运算符的语义存在技巧。仅包含运算符的表达式类型是该表达式的两个分支的通用类型(或可从其转换的类型),即使只评估了其中一个。现在,当编译器求值
true ? x.left : (node*)0
时,它将解析为表达式
x.left
,但其通用类型为
x.left
(node*)0
。它们基本上是同一类型,唯一的细节是that9是右值,而不是左值。     
可能是
const
,尽管它需要显式类型:
#define LEFT(X) ((const struct node *) (X->left))
...虽然具有
typeof
编译器扩展名:
#define LEFT(X) ((const typeof(X->left)) (X->left))
    

bab

对于C ++,我将使用一元+:
#define LEFT(X) (+((X)->left))
#define RIGHT(X) (+((X)->right))
对于一般的宏情况,这与添加ѭ16相比具有优势,它也适用于
void*
和函数指针。对于C,您可以使用逗号运算符
#define LEFT(X) (0, ((X)->left))
#define RIGHT(X) (0, ((X)->right))
    
我只是去一个明确的演员表
#define LEFT(X) ((struct node*)(X->left))
#define RIGHT(X) ((struct node*)(X->right))
这种强制转换的结果始终是右值。此外,如果您不想更改指针所指向的内容,以添加
const
,正如在另一个答案中已经给出的那样:
#define LEFT(X) ((struct node const*)(X->left))
#define RIGHT(X) ((struct node const*)(X->right))
    
您不会像这样编写\“ accessor \”宏,而是
typedef struct
{
  ...
} X;

X x;

#define LEFT (x.y.z.left)
然后,您可以像访问其他变量一样访问LEFT宏。这使代码更具可读性,同时有效地禁用了与类函数宏关联的整个不安全,难看,易出错,行为不确定的芭蕾舞。     

要回复问题请先登录注册