反对按位操作上的 int 强制转换

object to int casting on bitwise operation

本文关键字:int 转换 操作上 位操作      更新时间:2023-10-16

嗨,伙计们,这是我第二次尝试解释C++代码(我是一个非常新手(,我只想确保以下代码的含义C++:

//| Get other endpoint of an edge  |  
//+--------------------------------+    
inline Node *Node::NextNode( Edge *next)  
   {  
   return (Node *) ((!next) ? NULL : ( (int)next->node[0] ^ (int)next->node[1] ^ (int)this ) );  
   }

代码是否意味着将对象转换为next->node[0]next->node[1] int,并将 XOR 运算符应用于它们的位值? 并使用结果作为对Node*的引用作为回报?提前感谢您的帮助:)

是的。(虽然你也忽略了三元和演员阵容(

请记住,除非您非常小心,否则此类代码可能具有未定义的行为并且不可移植(例如,在 x86-64 上,指针大于整数(。

我在这里最好的猜测是Edge表示两个Node之间的边,定义如下

struct Edge {
    Node *node[2];
    // perhaps other fields
}

node中的两个元素都必须填写。它们可能指向不同的节点,或者至关重要的是,它们可能指向同一节点。

此外,Node::NextNode()只能传递一个Edge对象,该对象包含节点本身作为边缘上的两个node元素之一(或者可以传递 NULL(。

鉴于此,此函数基本上等价于

if (next) {
    if (next->node[0] == next->node[1]) return this;
    if (next->node[0] == this) return next->node[1];
    return next->node[0];
}
return NULL;

尽管正如 Antimy 指出的那样,它实际上是有缺陷的,因为它正在投射到 int 在任何指针大于整数的架构上都会表现不正确。当然,如果您不满足不变量,该函数的行为将不正确(例如,您传入的Edge不包含节点作为其两个node中的任何一个(。

你的解释是正确的。 这是非常奇怪的代码。 通常不会将一些整数x或在一起,而是将结果视为指针。

查看 node 声明附近的头文件,看看字段编码的内容。 如果没有这样的评论,请尽快逃离此代码!

(int)next->node[0] ^ (int)next->node[1] ^ (int)this

鉴于 next->node[0] 和 [1] 显然是指针,在隔离中看到它们的 XOR 提供了一个无意义的值(除了它们相等的微不足道的情况(,但考虑到期望与 this 进行 XOR 会产生有意义的东西,我假设其中一个 node[] 值已知是this的,这样我们就剩下没有this的那个。 换句话说,对于此方案,代码可能等效于:

next->node[next->node[0] == this]

(或者如果这有点神秘,你可能更喜欢next->node[next->node[0] == this ? 1 : 0];当一个数字是预期的时,C++ true转换为 1 和 false 转换为 0(

源代码中的注释"获取边缘的其他端点">似乎支持这一点:显然知道this是一个端点,并且代码找到"另一个"端点。

生成有效指针的另一种情况是,当node[0]node[1]相同时,将返回this。 如果打算支持此方案(而不仅仅是实现的巧合(,则上述建议的简化将失败。 你可以试试:

next->node[0] == next->node[1] ? this : next->node[next->node[0] == this]

如果对运行时数据是否可以包含两个相同的节点值有任何疑问,那么这种替换更安全。

正如其他人指出的那样,代码假设指针的大小与int相同,这很讨厌! 我不会像其他地方那样讨论它,但请记住这一点。