C++ 使用C++;11

C++ 使用C++;11,c++,c++11,endianness,compile-time,type-punning,C++,C++11,Endianness,Compile Time,Type Punning,关于这个话题,我在SO中提到了很多问题,但到目前为止还没有找到任何解决方案。这里提到了一种天然溶液:。 然而,评论中提到的相关问题&答案是相同的 经过一些修改,我能够在没有任何警告的情况下用g++&clang++(-std=c++11)编译类似的解决方案 static_assert(sizeof(char) == 1, "sizeof(char) != 1"); union U1 { int i; char c[sizeof(int)]; }; union U2 { char

关于这个话题,我在SO中提到了很多问题,但到目前为止还没有找到任何解决方案。这里提到了一种天然溶液:。
然而,评论中提到的相关问题&答案是相同的

经过一些修改,我能够在没有任何警告的情况下用g++&clang++(
-std=c++11
)编译类似的解决方案

static_assert(sizeof(char) == 1, "sizeof(char) != 1");
union U1
{
  int i;
  char c[sizeof(int)];
};  
union U2
{ 
  char c[sizeof(int)];
  int i;
};  

constexpr U1 u1 = {1};
constexpr U2 u2 = {{1}};
constexpr bool IsLittleEndian ()
{ 
  return u1.i == u2.c[0];  // ignore different type comparison
}   

static_assert(IsLittleEndian(), "The machine is BIG endian");


这可以被认为是一种确定endian属性的确定性方法,还是它错过了类型双关或其他什么?

您的尝试与这一显然不起作用的方法没有什么不同(其中
IsLittleEndian()
true
相同):

我相信C++11并没有提供在编译时通过编程确定目标平台的endianness的方法。我的论点是,在运行时执行该检查的唯一有效方法是使用
无符号char
指针检查
int
变量(因为其他类型双关方法不可避免地包含未定义的行为):

const uint32\u t i=0xffff0000;
布尔伊斯利特林迪安(){
返回0==*重新解释强制转换(&i);
}
C++11不允许使用此函数
constexpr
,因此无法在编译时执行此检查。

因为C++20可以从
标题使用:

#include <type_traits>

int main()
{
    static_assert(std::endian::native==std::endian::big,
                  "Not a big endian platform!");
}
#包括
int main()
{
静态断言(std::endian::native==std::endian::big,
“不是大端平台!”;
}

在两个端点上,uint8_t(u2.i)是否产生相同的值?强制转换应该保持值不变,而不仅仅是选择第一个字节。在一个4字节整数中,有24种可能的字节顺序。至少有三台被真正的计算机使用过。此外,授予[[
un
]
signed
]
char
的严格别名规则的例外情况是否适用于
uint8\u t
,这一点也不完全清楚。我相信,如果你真的在一台big-endian机器上运行它,它仍然会测试
1==1
并返回
true
sizeof(char)==1
定义为真
sizeof
是以字符为单位给出的,所以这个断言绝对不会失败。计划方案:你能更详细地解释一下为什么尝试的解决方案不起作用吗?或者为什么它和你们在答案开头提到的(非工作)一样。我没有机会检查big endian机器,但是我认为你说的是真的。但问题是为什么?@iammilind在你的“解决方案”中,工会的作用是什么?您从未访问/使用过
U1::c
,也从未访问/使用过
U2::i
。因此,在消除了它们之后,我们就得到了我的版本。这两个并集只是为了消除编译器错误,否则会产生一个并集。如果您选中
u1.i==u1.c[0]
(与
u2
相同),则它工作正常。在SO的许多其他答案中都有这种解决方案。但这些仅限于运行时。由于
constexpr
的限制,它们在编译时不工作。在这里,U1和U2充当彼此的镜像。我试图欺骗编译器,让它在编译时运行。也许这是错误的。但是如果有人用big-endian检查它,那就好了。@iammilind:我对
U2-U2={{{1}}
中初始化的理解是,它总是将数组的第一项设置为
1
。不是吗?BTW,C++ 20终于解决了这个问题:你来自未来吗?
const uint32_t i = 0xffff0000;

bool isLittleEndian() {
    return 0 == *reinterpret_cast<const unsigned char*>(&i);
}
#include <type_traits>

int main()
{
    static_assert(std::endian::native==std::endian::big,
                  "Not a big endian platform!");
}