c – 使用强制转换为“错误”类型的指针算法

前端之家收集整理的这篇文章主要介绍了c – 使用强制转换为“错误”类型的指针算法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个结构数组,我有一个指向其中一个结构的成员的指针.我想知道数组的哪个元素包含该成员.这有两种方法
#include <array>
#include <string>

struct xyz
{
    float x,y;
    std::string name;
};

typedef std::array<xyz,3> triangle;

// return which vertex the given coordinate is part of
int vertex_a(const triangle& tri,const float* coord)
{
    return reinterpret_cast<const xyz*>(coord) - tri.data();
}

int vertex_b(const triangle& tri,const float* coord)
{
    std::ptrdiff_t offset = reinterpret_cast<const char*>(coord) - reinterpret_cast<const char*>(tri.data());
    return offset / sizeof(xyz);
}

这是一个测试驱动程序:

#include <iostream>

int main()
{
    triangle tri{{{12.3,45.6},{7.89,0.12},{34.5,6.78}}};
    for (const xyz& coord : tri) {
        std::cout
            << vertex_a(tri,&coord.x) << ' '
            << vertex_b(tri,&coord.x) << ' '
            << vertex_a(tri,&coord.y) << ' '
            << vertex_b(tri,&coord.y) << '\n';
    }
}

两种方法都产生了预期的结果:

0 0 0 0
1 1 1 1
2 2 2 2

但它们是有效的代码吗?

特别是我想知道vertex_a()是否可能通过将float * y强制转换为xyz *来调用未定义的行为,因为结果实际上并不指向struct xyz.那个问题导致我写了vertex_b(),我认为这是安全的(是吗?).

这是GCC 6.3使用-O3生成代码

vertex_a(std::array<xyz,3ul> const&,float const*):
    movq    %rsi,%rax
    movabsq $-3689348814741910323,%rsi ; 0xCCC...CD
    subq    %rdi,%rax
    sarq    $3,%rax
    imulq   %rsi,%rax

vertex_b(std::array<xyz,float const*):
    subq    %rdi,%rsi
    movabsq $-3689348814741910323,%rdx ; 0xCCC...CD
    movq    %rsi,%rax
    mulq    %rdx
    movq    %rdx,%rax
    shrq    $5,%rax

解决方法

两者都不符合标准.

在vertex_a中,您可以将指向xyz :: x的指针转换为指向xyz的指针,因为它们是pointer-interconvertible

Two objects a and b are pointer-interconvertible if […] one is a standard-layout class object and the other is the first non-static data member of that object […]

If two objects are pointer-interconvertible,then they have the same address,and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast.

但你不能从指向xyz :: y的指针转换为指向xyz的指针.该操作未定义.

在vertex_b中,你要减去两个指向const char的指针.该操作在[expr.add]中定义为:

If the expressions P and Q point to,respectively,elements x[i] and x[j] of the same array object x,the expression P - Q has the value i − j; otherwise,the behavior is undefined

您的表达式不指向char数组的元素,因此行为未定义.

猜你在找的C&C++相关文章