C语言struct位域符号问题

C语言位域符号问题

1. 引言

本来没打算写这篇文章,但最近在项目中遇到了位域这个问题,问题大概就是,在没有越界的情况下,一个位域吃进去的值和吐出来的值居然不一样,虽然知道位域这个东西比较节省空间,但从没有深究这个东西,现在既然遇到坑了,就研究了一下,拿出来和大家分享一下,也不是很难的东西,算是生活常识吧。

2. 结论及测试程序

由于知识点比较简单,我就先说结论吧。结论就是:(1)对于有符号类型的位域,最高位会被解析为符号位,在进行%d输出时,会以算术移位进行位扩展。比如一个位域 int32_t a : 4, 在进行%d输出时,会将a从4位扩展成32位,中间扩展的内容和符号位相同,即算术移位;(2)对于无符号类型的位域,不存在符号位,在进行扩展时,扩展位全部补0。测试程序如下:

#include <iostream>
#include <stdio.h>
#include <stdint.h>
using namespace std;

struct SignedNode {
    int32_t a : 2;
    int32_t b : 2;
    int32_t c : 2;
};

struct UnsignedNode {
    uint32_t a : 2;
    uint32_t b : 2;
    uint32_t c : 2;
};

int main(int args, char *arg[]) {
    SignedNode s_node;
    UnsignedNode us_node;
 
    s_node.a = 1;
    s_node.b = 2;
    s_node.c = 3;

    us_node.a = 1;
    us_node.b = 2;
    us_node.c = 3;

    printf("SignedNode Dec Value: a = %d, b = %d, c = %d\n", s_node.a, s_node.b, s_node.c);
    printf("UnsignedNode Dec Value: a = %d, b = %d, c = %d\n", us_node.a, us_node.b, us_node.c);

    printf("SignedNode Hex Value: a = %p, b = %p, c = %p\n", s_node.a, s_node.b, s_node.c);
    printf("UnsignedNode Hex Value: a = %p, b = %p, c = %p\n", us_node.a, us_node.b, us_node.c);
    return 0;
}
测试环境为:gcc 4.8.2

测试结果为:

SignedNode Dec Value: a = 1, b = -2, c = -1
UnsignedNode Dec Value: a = 1, b = 2, c = 3
SignedNode Hex Value: a = 0x1, b = 0xfffffffe, c = 0xffffffff
UnsignedNode Hex Value: a = 0x1, b = 0x2, c = 0x3

3.测试结果分析

(1)SignedNode的测试中,a,b,c各占2位,二进制分别位01,10,11,符号位的值分别位0,1,1,它们的类型仍旧是int32_t,在进行%d输出时,会把它们扩展成int32_t类型,扩展后变成a = 0x00000001,b = 0xFFFFFFFE,c = 0xFFFFFFFF,转换成十进制也就是1,-2,-1。

(2)UnsignedNode的测试中,a,b,c也各占2位,二进制分别为01,10,11,由于都是uin32_t类型,所以不存在符号位,但仍旧需要扩展成uint32_t类型,所以直接高位补0即可,扩展后变成a = 0x00000001,b = 0x00000002,c = 0x00000003,转换成十进制也就是1,2,3。


综上所示,位域的扩展实际和位域本身的类型息息相关,对于有符号类型和无符号类型扩展后的结果不同,但二者扩展的原理相同。我尝试过用共用体按字节打印出SignedNode的内容,但每次输出的结果都不同,看不出位域在存储层面的结构,而且位域地址打印也不合法,可能是自己方法不得当,如果有哪位大神知道如何从存储层面分析位域的好方法,还望指点一二,不甚感激。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值