不使用*操作符hack-y方式获取产品

有人可以帮助我理解以下逻辑如何解决获得a和 的产品b吗?

int getProd(int a, int b){
    return (uintptr_t)&((char (*) [a])0x0)[b];
}

回答

假设我们有一个指针p,它指向大小为 的对象a

如果我们接着说p + b,我们就要求一个指向b经过 wherep点的第 ' 个对象的指针。

因此,实际的新指针值(无论如何在字节寻址的机器上)将按 缩放a,即指向对象的大小。也就是说,“在幕后”,编译器将做一些更像p + b * a.

所以我们可以看到乘法a * b正在发生——但随后它被添加到 的原始值中p

因此,如果我们使用初始值 0,我们将得到a * b. 这就是 hackygetProd函数正在做的事情。

让我们分解一下:

                           0x0

值 0,在指针上下文中也称为空指针。[脚注:这个定义更复杂,但我们暂时不要担心。]

              char (*) [a]

这是一种类型:“指向char大小为数组的指针a

             (char (*) [a])0x0

这是一个强制转换:获取该空指针,将其强制转换为“指向数组[a]的指针char”类型。

            ((char (*) [a])0x0)[b]

拿那个指针,想象它指向一个数组,然后获取该数组的第b' 个元素。由于数组索引与指针算术相同,因此最终会计算0 + a * b

           &((char (*) [a])0x0)[b];

我们引用b了“数组”的第 ' 个元素。现在,计算一个指针该元素。该指针应该从字面上具有 value 0 + a * b

(uintptr_t)&((char (*) [a])0x0)[b];

最后,获取该指针并将其强制转换为整数类型。


现在,说了这么多,必须指出这是一个hack。以这种方式编写对空指针执行算术的代码是非常有问题的。它可能几乎但不完全合法;它可能是合法的,但几乎不合法。你可以就答案落在这条线的哪一边争论几个小时。

在这种情况下,当然,这是一种学术争论,因为没有人会认真地建议以这种方式进行乘法。


以上是不使用*操作符hack-y方式获取产品的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>