有没有什么窍门禁止C宏被称为左值?
struct node {
struct node *left, *right;
};
#define LEFT(X) (X->left)
#define RIGHT(X) (X->right)
我想禁止这样的宏调用不改变现有的宏接口。
LEFT(n) = ...
任何想法?
#undef LEFT
#undef RIGHT
//template<class T>
inline const node * const LEFT(const node * X) {
return X->left;
}
这里的T是什么? – sharptooth 2011-04-15 11:16:29
有点smarmy,但+1。最好的建议是根本不使用宏。 – 2011-04-15 11:16:43
用C++你没有宏... – Petesh 2011-04-15 11:17:09
也许const
,但它需要一个明确的类型:
#define LEFT(X) ((const struct node *) (X->left))
...但如果你有typeof
编译器扩展:
#define LEFT(X) ((const typeof(X->left)) (X->left))
这些仍然是左值。 OP正试图使它不可能编辑指针,而不是它指向的数据。 – 2011-04-15 11:28:58
我会用内联函数去,但如果你想要一个宏:
#define LEFT(X) (1 ? (X)->left : 0)
你可以使用三元运算符来CE宏的结果是右值,但错误信息可能会造成混淆用户:
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
。他们两个基本上是相同的类型,唯一的细节(node*)0
是一个右值,而不是一个左值。
或者直接写'node * l = n.left;'......问题解决了。 – Lundin 2011-04-15 11:50:41
我刚刚去了一个明确的转换
#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))
你不写这样的“访问”宏,你做
typedef struct
{
...
} X;
X x;
#define LEFT (x.y.z.left)
然后,像访问其他变量一样访问LEFT宏。这使得代码更具可读性,同时有效地禁用与功能宏相关的整个不安全,丑陋,容易出错,未定义行为的芭蕾。
对于C++,我会用一元+:
#define LEFT(X) (+((X)->left))
#define RIGHT(X) (+((X)->right))
对于一般的宏观情况下,这个拥有添加+0
,它也适用于void*
和函数指针的优势。对于C,您可以使用逗号运算符
#define LEFT(X) (0, ((X)->left))
#define RIGHT(X) (0, ((X)->right))
一般来说,这比我的回答好,因为它也适用于'void *'。对于OP的问题,这并不重要。 – 2011-04-15 12:23:36
@R ..,你是对的。更新我的答案更精确:) – 2011-04-15 12:26:18
最后我加入'+ 0'在我的代码,因为使用逗号操作这种方式产生了大量的“表达式结果未使用”警告 – wsxiaoys 2011-04-15 12:33:04
该宏是做什么的?我不明白你为什么需要这样的宏。 – Lundin 2011-04-15 11:48:02
@Lundin我以此为例。对于真正的代码,有很多深层次的成员,accessor-macros会很有用。 – wsxiaoys 2011-04-15 11:52:22
@wsxiaoys好的,我明白了。我会用一个例子说明你应该如何做这样的宏。 – Lundin 2011-04-15 11:58:16