使用C ++ 11

时间:2016-09-29 07:05:57

标签: c++ c++11 endianness compile-time type-punning

我在SO中提到了很多关于这个主题的问题,但到目前为止找不到任何解决方案。这里提到了一个自然的解决方案:Determining endianness at compile time 但是,评论中提到的相关问题&同样的答案。

通过一些修改,我能够用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 =   angular
.module("app", [])
.controller("appController", function ($scope) {

  $scope.Data = [
    {
      Percent: 25.0,
      Value: 1000.0
    },
    {
      Percent: 25.0,
      Value: 1000.0
    },
    {
      Percent: 25.0,
      Value: 1000.0
    },
    {
      Percent: 25.0,
      Value: 1000.0
    }
  ];
  $scope.TotalAmount = 4000.0;
  
  $scope.changeCalled = function(invoice, flag, index){
    var per=0;
    var value=0;
    if(flag == 'per')
    {
        value = ($scope.TotalAmount * invoice.Percent)/100;
        $scope.Data[index].Value = value;
    }
    else if(flag == 'val')
    {
        per = (invoice.Value * 100) / $scope.TotalAmount;
        $scope.Data[index].Percent = per;
    }
    $scope.updateResult(index);
  }
  $scope.updateResult = function(index, flag){
    var remainedPer = 0;
    var remainedVal = 0;
    remainedPer = (100 - $scope.Data[index].Percent)/ ($scope.Data.length - 1);             
    remainedInput = ($scope.TotalAmount - $scope.Data[index].Value)/ ($scope.Data.length - 1); 
    for(i=0; i<$scope.Data.length; i++)
    {
        if(i != index)
        {   
            $scope.Data[i].Percent = remainedPer;
            $scope.Data[i].Value = remainedInput;
        }
    }
  };
});;
constexpr bool IsLittleEndian ()
{ 
  return u1.i == u2.c[0];  // ignore different type comparison
}   

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

Demo

这可以被认为是决定字节序的确定性方法还是错过了类型惩罚或其他什么?

2 个答案:

答案 0 :(得分:2)

您的尝试与明显不合作的(IsLittleEndian()true相同)没有什么不同:

constexpr char c[sizeof(int)] = {1};
constexpr int i = {1};
constexpr bool IsLittleEndian ()
{ 
  return i == c[0];  // ignore different type comparison
}   

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

我相信C ++ 11并没有提供在编译期间以编程方式确定目标平台的字节顺序的方法。我的论点是,在运行时执行检查的唯一有效方法是使用int指针检查unsigned char变量(因为其他类型的惩罚方式不可避免地包含未定义的行为):

const uint32_t i = 0xffff0000;

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

C ++ 11不允许创建此函数constexpr,因此在编译期间无法执行此检查。

答案 1 :(得分:1)

从C ++ 20开始,您可以使用<type_traits>标头中的std::endian

#include <type_traits>

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

See it live