从 int 到 class 的类型转换行为异常

type conversion from int to class behaving weirdly

提问人:rashi 提问时间:10/26/2022 最后编辑:Spencerrashi 更新时间:10/27/2022 访问量:82

问:

所以。我正在尝试将uint16_t(16 字节 int)转换为类。获取类成员 varaible。但它没有按预期工作。


class test{
public:
    uint8_t m_pcp : 3; // Defining max size as 3 bytes
    bool m_dei : 1;
    uint16_t m_vid : 12; // Defining max size as 12 bytes

public:
    test(uint16_t vid, uint8_t pcp=0, bool dei=0) {
        m_vid = vid;
        m_pcp = pcp;
        m_dei = dei;
    }
};

int main() {
    uint16_t tci = 65535;
    test t = (test)tci;

    cout<<"pcp: "<<t.m_pcp<<" dei: "<<t.m_dei<<" vid "<<t.m_vid<<"\n";
    return 0;
}

预期输出:

pcp:1  dei: 1 vid 4095

实际输出:

pcp:  dei: 0 vid 4095

cout<<sizeof(t)

返回 2。不应该是4吗?

我做错了什么吗?

C++ 类型转换 位域 UITint16

评论

0赞 NathanOliver 10/26/2022
为什么会这样?您有总共 16 位的位字段,因此您的类只需要 2 个字节宽。4
0赞 Pepijn Kramer 10/26/2022
另请注意:位域存储器布局是实现定义的。因此,内存布局可能不符合您的期望。位字段仅保证值(模或有符号溢出)的正确算术。因此,您必须检查编译器为您的特定处理器实际生成的内容。en.cppreference.com/w/cpp/language/bit_field
1赞 Nelfeal 10/26/2022
您不是强制转换为 ,而是使用默认值调用构造函数。tcitest
0赞 Pete Becker 10/26/2022
回复:“uint16_t (16 byte int)” -- 应该是 16 int。所有关于位域大小的注释都相同;数字是位数,而不是字节数。

答:

-1赞 Scott Settlemier 10/26/2022 #1

位字段总共有 16 位,因此 2 个字节的大小是正确的。(编译器会将相邻的位字段打包在一起 - 但要小心,因为可能因编译器而异)单个 uint16_t 值的构造函数仅将值的 12 位分配给 m_vid,将 0 分配给其他成员。65535 的前 12 位是 4095,因此输出是正确的,正如您所注意的那样(注意:您对位字段是字节的注释应为“位”),但您对其他位的期望是偏离的。构造函数明确表示,如果未指定,则为它们提供 0 值。

1赞 Nelfeal 10/26/2022 #2
test t = (test)tci;

此行不会执行您期望的强制转换(这将是 ,但它不会编译)。它只是使用默认值调用构造函数。因此被分配截断为 12 位,并且被分配 。尝试删除构造函数以查看它是否未编译。reinterpret_castm_vid65535m_pcpm_dei0

我知道做你想做的事的唯一方法是编写一个正确的构造函数,如下所示:

test(uint16_t i) {
    m_vid = i & 0x0fff;
    i >>= 12;
    m_dei = i & 0x1;
    i >>= 1;
    m_pcp = i & 0x7;
}

演示

另外,我不确定为什么你会期望是 1,因为 65535 的 3 位最高位等于 7。m_pcp

此外,返回 2。不应该是4吗?cout<<sizeof(t)

不,3+1+12=16 位等于 2 个字节。