【问题标题】:Type casting struct to integer c++将结构类型转换为整数 c++
【发布时间】:2014-09-08 23:15:47
【问题描述】:

我的设计要求值包含在 32 位字内的某些位中。示例是位 10-15 必须保持值 9,其余位均为 0。因此,为了简单/可读性,我创建了一个结构,其中包含所要求内容的分解版本。

struct {
    int part1 : 10;
    int part2 : 6;
    int part3 : 16;
} word;

然后我可以将part2 设置为等于请求的任何值,并将其他部分设置为 0。

word.part1 = 0; 
word.part2 = 9;
word.part3 = 0;

我现在想要获取该结构,并将其转换为单个 32 位整数。我确实通过强制转换来编译它,但它似乎不是一种非常优雅或安全的数据转换方式。

int x = *reinterpret_cast<int*>(&word);

如果我尝试将其转换为普通的reinterpret_cast&lt;int&gt;(word),则会收到以下错误:

invalid cast from type 'ClassName::<anonymous struct>' to type 'int'

必须有更好的方法来做到这一点,我就是想不通。提前致谢!

注意:必须在 c++ 风格的转换中完成,因为标准等等...... 眼睛滚动

【问题讨论】:

  • 是的,现在我不再为 IBM 工作,我只想使用工会。 (不能在 IBM 中提到 U 字,你知道。)
  • 请注意,这些位域在int 内的位置没有定义,只有它们占用的位数。
  • @HotLicks 是的,它不是 IBM,但绝对是一个有着相似观点的地方 :)

标签: c++ struct


【解决方案1】:
union Ints {
  struct {
    int part1 : 10;
    int part2 : 6;
    int part3 : 16;
 } word;
 uint32_t another_way_to_access_word;
};

可能有帮助

【讨论】:

  • 我隐约记得在标准中有一些狡猾的措辞,工会可以有“未记录的行为”,但以上内容应该适用于任何合理的编译器。
  • @HotLicks:有黄鼠狼的措辞,但没人在乎。
  • @MooingDuck:过去人们对未定义的行为持这种态度。然后编译器升级将他们“应该与任何合理的编译器一起工作”的代码变成了安全漏洞。
  • @BenVoigt 和人们的回应是指责编译器作者
  • FWIW 这不是 C11 中的 UB,它明确表示联合别名覆盖了严格的别名规则(C++11 没有这样说)。但我不清楚这段代码是否违反了 C++ 严格别名。 (允许将 int 别名为 unsigned int,但我不确定作为位域的 int 是否会改变)
【解决方案2】:
typedef struct word {
  uint32_t part1 : 10;
  uint32_t part2 : 6;
  uint32_t part3 : 16;

  operator int() const{
    return (part1 << 22) + (part2 << 16) + part3;
  }

  word& operator=(int i){
    this->set(i);
    return *this;
  }

  void set(int i){
    part1 = (0xFFFF0000 & i) >> 16;
    part2 = (0x0000FC00 & i) >> 10;
    part3 = (0x000003FF & i);
  }

  word(int i){
    this->set(i);
  }
} word;

应该可以的。

struct word myword = 20;
struct word second_word(50);

myword = 10;
second_word.set(50);

int x = myword;
iny y = second_word;

注意:已编译并检查。

【讨论】:

    【解决方案3】:

    尝试reinterpret_cast&lt;int&gt;(word) 不起作用,因为在您的用户定义的结构类型和int 之间没有定义转换运算符。

    您可以在结构中添加一个转换运算符,或者最好是恕我直言,一个命名函数来进行转换,例如:

    struct {
        uint32_t part1 : 10;
        uint32_t part2 : 6;
        uint32_t part3 : 16;
    
        uint32_t get_all_parts() const
        {
             return (part1 << 22) + (part2 << 16) + part3;
        }
    } word;
    

    注意,我使用无符号整数,因为它们在左移时具有明确定义的行为。

    【讨论】:

    • 这也可以,但我一直在寻找一些我不必编写像您的 get_all_parts 代码 b/c 这样的小子函数的东西,这必须多次完成。我的值实际上是实际(未简化)代码中的无符号整数,但为了简单起见,我删除了它
    • 所以添加一个转换运算符。
    猜你喜欢
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2020-09-02
    • 2012-11-23
    相关资源
    最近更新 更多