c++ - 我可以重新解释_cast constexpr 函数的参数吗?

标签 c++ compiler-errors bit-manipulation c++17 constexpr

我想编写一个在编译时计算的函数,它接受一个指向 4 字节数组的指针,并输出一个与该数组具有相同位模式的 int。 所以我想出了:

constexpr int f(const char* p) {
     return *reinterpret_cast<int*>(p);
}

然后,我想像这样使用 f():

switch(x) {
case f("GOOG"):
   // do something
case f("MSFT"):
   // do something
case f("NIKE"):
  // do something
}

但是,我遇到了一个编译错误:

error: accessing value of ‘"GOOG"’ through a ‘int’ glvalue in a constant expression case f("GOOG")
  1. 如何修复 f() 以便编译?
  2. 是否有更好的方法来实现相同的目标?

最佳答案

恭喜,您已经激活了严格的别名陷阱卡并且您的代码具有未定义的行为(如果它可以编译)。

您的代码中几乎没有错误,“正确”版本是:

 constexpr int f(const char* p) {
         return *reinterpret_cast<const int*>(p);
    }
  • reinterpret_cast 无法丢弃 const
  • cursor->p 打字错误?

但由于 const char* 不指向 int,转换为它打破了严格的别名规则。 int 不是可以为其他类型起别名的类型之一 - 只有 std::byte, (unsigned) char 可以。

最干净的是这样的:

#include <cstring>

constexpr int f(const char* p) {
         int val = 0;
         static_assert(sizeof(val)==4); // If the array is 4-byte long.
         std::memcpy(&val,p,sizeof val);
         return val;
    }

std::memcpy 不是 constexpr,即使在运行时这可能不会有任何开销,编译器可以识别这一点并自行重新解释字节.

所以进行位移:

constexpr int f(const char* p) {
       int value=0;
       using T = decltype (value);
       for(std::size_t i =0; i< sizeof(T);++i)
        value|= (T)p[i] << (8*i);

    return value;
    }

int main(){

    // @ == 64
    // 1077952576 = 01000000 01000000 01000000 01000000
    static_assert(f("@@@@") ==1077952576);
}

只是迂腐 "@@@@" 的长度是 5,而不是 4。

关于c++ - 我可以重新解释_cast constexpr 函数的参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64040944/

相关文章:

c - ~ 一元运算符和按位测试给出否定结果

ruby - 简单异或 ruby​​ 1.9.2

C++ 非静态成员函数开销

c++ - 有没有办法让这个 C++14 递归模板在 C++17 中更短?

c++ - SMTP编译错误

c - 使用指针手动复制字符串时出错

java - 如何检查 TarArchiveEntry 是否设置了 3 个执行位中的任何一个?

c++ - Linux 数据模型和原始类型大小

c++ - 如何实现中点位移

c++ - C++自定义范围类型MSVC可以编译,但G++不能