c ++ 11严格的别名规则是否允许通过char *,char(&)[N],甚至std :: array< char,N&>访问uint64_t与-fstrict-aliasing -Wstrict-aliasing = 2吗? [英] Do the c++11 strict alias rules allow accessing uint64_t via char *, char(&)[N],even std::array<char, N>& with -fstrict-aliasing -Wstrict-aliasing=2?

查看:162
本文介绍了c ++ 11严格的别名规则是否允许通过char *,char(&)[N],甚至std :: array< char,N&>访问uint64_t与-fstrict-aliasing -Wstrict-aliasing = 2吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 stackoverflow答案,有关 C ++ 11/14 严格的别名规则:

According to this stackoverflow answer about C++11/14 strict alias rules:

如果程序尝试通过以下类型之一以外的glvalue访问对象的存储值,则 行为未定义:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • 对象的动态类型

  • the dynamic type of the object,

对象动态类型的cv限定版本,

a cv-qualified version of the dynamic type of the object,

我们可以使用

(1)char *

(2)char(&)[N]

(3)std::array<char, N> &

不取决于未定义的行为吗?

constexpr uint64_t lil_endian = 0x65'6e'64'69'61'6e; 
    // a.k.a. Clockwise-Rotated Endian which allocates like
    // char[8] = { n,a,i,d,n,e,\0,\0 }

const auto& arr =   // std::array<char,8> &
    reinterpret_cast<const std::array<char,8> &> (lil_endian);

const auto& carr =  // char(&)[8]>
    reinterpret_cast<const char(&)[8]>           (lil_endian);

const auto* p =     // char *
    reinterpret_cast<const char *>(std::addressof(lil_endian));

int main()
{
    const auto str1  = std::string(arr.crbegin()+2, arr.crend() );

    const auto str2  = std::string(std::crbegin(carr)+2, std::crend(carr) );

    const auto sv3r  = std::string_view(p, 8);
    const auto str3  = std::string(sv3r.crbegin()+2, sv3r.crend() );

    auto lam = [](const auto& str) {
        std::cout << str << '\n'
                  << str.size() << '\n' << '\n' << std::hex;
        for (const auto ch : str) {
            std::cout << ch << " : " << static_cast<uint32_t>(ch) << '\n';
        }
        std::cout << '\n' << '\n' << std::dec;
    };

    lam(str1);
    lam(str2);
    lam(str3);
}

所有lambda调用都会产生:

all lambda invocations produce:

endian
6

e : 65
n : 6e
d : 64
i : 69
a : 61
n : 6e

godbolt.org/g/cdDTAM (启用-fstrict-aliasing -Wstrict-aliasing = 2)

godbolt.org/g/cdDTAM (enable -fstrict-aliasing -Wstrict-aliasing=2 )

wandbox.org/permlink/pGvPCzNJURGfEki7

推荐答案

char(&)[N]情况和std::array<char, N>情况均导致未定义的行为.原因已被您阻止引用.请注意,char(&)[N]std::array<char, N>都不是与char相同的类型.

The char(&)[N] case and std::array<char, N> case both result in undefined behavior. The reason has already been block-quoted by you. Note neither char(&)[N] nor std::array<char, N> is the same type as char.

我不确定char的情况,因为当前标准并未明确指出对象可以看成是由窄字符组成的数组(请参见

I am not sure of the char case, because the current standard does not explicitly say that an object can be viewed as an array of narrow characters (see here for further discussion).

无论如何,如果要访问对象的基础字节,请使用std::memcpy,如标准在

Anyway, if you want to access the underlying bytes of an object, use std::memcpy, as the standards explicitly says in [basic.types]/2:

对于平凡可复制的类型T的任何对象(基类子对象除外),无论该对象是否持有类型T的有效值,组成该对象的基础字节([intro.memory])都可以是复制到char,unsigned char或std​::​byte([cstddef.syn])的数组中.如果该数组的内容被复制回该对象,则该对象随后应保持其原始值. [示例:

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std​::​byte ([cstddef.syn]). If the content of that array is copied back into the object, the object shall subsequently hold its original value. [ Example:

#define N sizeof(T)
char buf[N];
T obj;                          // obj initialized to its original value
std::memcpy(buf, &obj, N);      // between these two calls to std​::​memcpy, obj might be modified
std::memcpy(&obj, buf, N);      // at this point, each subobject of obj of scalar type holds its original value

-示例]

这篇关于c ++ 11严格的别名规则是否允许通过char *,char(&amp;)[N],甚至std :: array&lt; char,N&amp;&gt;访问uint64_t与-fstrict-aliasing -Wstrict-aliasing = 2吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆