Using pointer conversions to store/cast values: Am I breaking the strict aliasing rule?

时间秒杀一切 提交于 2020-01-09 11:42:28

问题


The question relates to this post.

Some authoritative users stated that the following code breaks strict aliasing rules.

#include <boost/static_assert.hpp>

template <typename T>
struct MyType {

    private:
    T data;

    public:
    template <typename U>
    operator U () {
        BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to convert to data type of different size");
        return *((U*) &data);
    }

    template <typename U>
    NeonVectorType<T>& operator =(const U& in) {
        BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to copy from data type of different size");
        data = *((T*) &in);
        return *this;
    }
}

However, I am never using a pointer to write data, and I am never sharing a pointer to it, so I cannot see how value contained in a variable can change without the compiler realizing that this is happening. My impression is that maybe I am breaking some rules, but not the strict aliasing ones...

Note: I don't know how much this matters, but my compiler (gcc 4.9) does not issue warnings.


回答1:


*((U*) &data) will violate strict aliasing if this is a reinterpret_cast and the type U is not permitted to alias the type T. The permitted types appear in this list.

The rule refers to both reading and writing.

Here is a good article that explains some of the rationale behind the rules.

As noted on the main strict aliasing thread, you can use memcpy as work around , for example:

U u;
memcpy( &u, &data, sizeof u );
return u;

and in the other function

memcpy( &data, &in, sizeof data );

Note that raw byte copies of class types are subject to some restrictions (I think the classes have to be POD, and you'd better be sure they have the same layout).




回答2:


However, I am never using a pointer to write data [...]

The language in the standard is more general than this; [basic.life]/7 has:

[...] a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object [...]

In your operator= you're using an lvalue of type T to write to data, and in operator U you're using a pointer of type U to read it; where U and T are unrelated and not character types this is UB.

Just use memcpy. It's guaranteed to work, and it's efficient (try it)!



来源:https://stackoverflow.com/questions/29253100/using-pointer-conversions-to-store-cast-values-am-i-breaking-the-strict-aliasin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!