0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

整型的signed和unsigned详解 double的二进制位显示

xCb1_yikoulinux 来源:一口Linux 作者:土豆居士 2022-06-06 17:01 次阅读

C语言各种数据类型的内存映像(32位平台):

c13a9904-e420-11ec-ba43-dac502259ad0.png

0 signed char

#include int main(){    char min = 1<<7;    char max = (1<<7)-1;    for(int i=min;i<=max;i++)        if(i<0)            printf("%.2X ",(unsigned char)i);        else
        {            printf("%c ",i);            if(i%32==0)                printf("
%d ",i);
        }
    getchar();
}

output:

c15be8de-e420-11ec-ba43-dac502259ad0.png

1 整型的signed和unsigned

#include int main(){    signed int smin = 1<<31;    signed int smax = (1<<31)-1;    printf("%d
",smin);    // -2147483648
    printf("%d
",smax);    // 2147483647
    unsigned int umax = -1;    printf("%u
",umax);    // 4294967295
    umax = (1<<32)-1;    printf("%u
",umax);    // 4294967295}

如果一个表达式同时包含signed和unsigned整型,signed会提升为unsgined,可能会隐藏一些意想不到的错误,特别是用在比较运算时:

    unsigned int a=4294967290;    int b=-6; 
    printf("%d
",a==b); // 1 , b promotes to unsigned

2 double的二进制位显示

#include void printByte(double d){    int bs = sizeof d;    unsigned char *ch = (unsigned char*)&d;    for(int i=0;iprintf("%.2X ",*(ch+i));
}int main(){    int n = 0x01020304;    if(*(char*)&n == 4)        printf("小端:");//小端:
    double d = 15.75; // 1111.11, 指数位值:1023+3
    //0 100 0000 0010 1111100000000000000000000000000000000000000000000000
    printByte(d);//00 00 00 00 00 80 2F 40
    // 40              2F               80
    // 0100 0000 0010 1111 1000 0000
    getchar();
}

将double分成4部分显示:

#include typedef struct packed_double {
    unsigned int low32;    // 小数位 低32位
    unsigned int low20:20; // 小数位 低33-52位
    unsigned int exp11:11; // 指数位 低53-63位,移码1023+二进制整数位-1
    unsigned int sign:1;  // 符号位} packed_double;typedef union {    double d;
    packed_double b;
} packed;int main(){
    packed pd;
    pd.d = -15.75;
    pd.d = 12.3;    printf("%u %u %u %u
",pd.b.sign,pd.b.exp11,pd.b.low20,pd.b.low32);
    getchar(); 
    return 0;
}/*
0 1026 1015808 0
*/

3 数组是相同数据类型的依次存储

数组名是一个存储数据首元素地址具有常量性质的特殊指针,成员是相对于基址的偏移:

#include void printArr(short arr[],int len){    for(int i=0;iprintf("%d ",*(arr+i));
    }    printf("
");
}int main(){
    short arr[] = {1,3,2};    int len = sizeof arr / sizeof *arr;
    printArr(arr,len);
}

4 枚举只是枚举可以取值的一些符号常量的一个特殊整型

#include int main(){    enum Nm{LOSS,TIE,WIN}nm; // 实质是一个整型,成员只是可能的右值(符号常量)的枚举
    nm = LOSS;    printf("%d ",nm); // 0
    nm = TIE;    printf("%d ",nm); // 1
    nm = WIN;    printf("%d ",nm); // 2
    nm = (enum Nm)3;  
    printf("%d ",nm); // 3
    printf("
%d",sizeof(enum Nm)); // 4
    getchar();
}

枚举让相关符号常量内聚为一组,相对于#define,枚举对数据的描述性更清晰。

5 共用体成员的起始地址相同,共用一块内存空间,值相互覆盖

#include int main(){    union Nn{int a; double b;}nn;// 成员的起始地址相同,值相互覆盖
    nn.a = 123; // 
    printf("起始地址:%X,内存空间占用:%d
",&nn.a,sizeof nn.a);
    nn.b = 12.3;    printf("起始地址:%X,内存空间占用:%d
",&nn.a,sizeof nn.b);
    nn.a = 12;    printf("起始地址:%X,内存空间占用:%d
",&nn.a,sizeof nn.a);
    getchar();
}/*
起始地址:12FF40,内存空间占用:4
起始地址:12FF40,内存空间占用:8
起始地址:12FF40,内存空间占用:4
*/

当一些事物具有更多共性,但有少量差异时,可以只用一个内嵌一个共用体的结构体来描述:

#include #include #define MAXPARTS 12struct Parts{ // 零件
int cost;char supplier[12];char unit[12] ;
};struct Assembly{ // 装配件
int n_parts;struct {
char partno[12];
short quan;
}parts[MAXPARTS];
};struct Inventory{ // 存货类型,或是零件,或是装配件
char partno[10];int quan;enum{PART,ASSEMBLY}type; // 存货类型
union {struct Parts parts;
struct Assembly assembly;
}info;
};int main(){struct Inventory screen;
strcpy(screen.partno,"p001");
screen.quan = 12;
screen.type = Inventory::PART;
screen.info.parts.cost = 122;strcpy(screen.info.parts.supplier,"hw");strcpy(screen.info.parts.unit,"pcs");
struct Inventory shell;
strcpy(shell.partno,"a001");
shell.quan = 4;
shell.type = Inventory::ASSEMBLY;
shell.info.assembly.n_parts=22;strcpy(shell.info.assembly.parts[0].partno,"d001");
shell.info.assembly.parts[1].quan = 5;int costs;if(shell.type == Inventory::ASSEMBLY)
costs = shell.info.assembly.n_parts;
printf("%d
",costs); //22
getchar();return 0;
}

6 结构体是不同数据类型的数据依次存储在一起

结构体各数据成员的引用可以通过其内存大小和字节对齐来相对于基址偏移来计算。结构体通常用于描述某一事物,用其成员来描述该事物的某些关键属性。让该事物既可以用结构体变量整体表示,也可以对其成员分别引用来处理该事物的各个属性。

#include int main()
{    struct demo{char a; short b;int c;} abc; // 成员相对于基址偏移,字节对齐
    abc.b=12;    short *p = (short*)((int)&abc+sizeof(short)); // 模拟编译器计算第2个成员的偏移地址
    printf("%d %d
",abc.b,*p); // 12 12
    printf("%d
",sizeof(struct demo));// 8
    getchar();
}

7 位域是对整型数据的按位处理

(一次可以处理n个位,1<=n<=整形长度)

位域(全局)二进制位显示:

#include void printBinM(unsigned int n){    for(int i=31;i>=0;i--)        printf("%d",(n & 1<>i);    printf("
");
}struct Bf{    
    unsigned a:3;    
    unsigned b:4;    
    unsigned c:5;
}bf;int main(){
    bf.a =1;
    bf.b=15;
    bf.c=3;    int *p = (int*)&bf; // 505
    printf("%d
",*p);
    printBinM(*p);//00000000000000000000000111111001
    getchar();
}

位域(局部)二进制位显示:

#include void printBinM(unsigned int n){    for(int i=31;i>=0;i--)        printf("%d",(n & 1<>i);    printf("
");
}int main(){    struct Bf{    
        unsigned a:3;    
        unsigned b:4;    
        unsigned c:5;
    }bf;
    bf.a =1;
    bf.b=15;
    bf.c=3;    int *p = (int*)&bf; // -858996231
    printf("%d
",*p);
    printBinM(*p);//11001100110011001100000111111001
    getchar();
}

原文标题:7 位域是对整型数据的按位处理

文章出处:【微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7528

    浏览量

    128412
  • Doubler
    +关注

    关注

    0

    文章

    7

    浏览量

    7143
  • 数据类型
    +关注

    关注

    0

    文章

    227

    浏览量

    13489

原文标题:7 位域是对整型数据的按位处理

文章出处:【微信号:yikoulinux,微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    二进制详解

      Binary-Coded-Decimal,二进制编码的十进制码。  这种编码仅仅使用4二进制数来表示十进制数中的0~9十个数码。
    发表于 04-06 23:55

    二进制格雷码与自然二进制码的互换

    都可读出一个固定的与位置相对应的数字码;抗干扰能力强,没用累积误差;电源切断后位置信息不会丢失,但分辨率是由二进制的位数决定的,根据不同的精度要求,可以选择不同的分辨率即位数。目前有10、11、12
    发表于 03-08 14:16

    二进制显示数组

    请教各位大神如何将一个十进制数组变成二进制显示??我是初学者,在数组属性里的显示格式里,二进制不可选,是不是需要数据转换???请各位大神不吝
    发表于 11-28 11:21

    基于FPGS二进制LDPC

    一个8二进制数经过二进制LDPC编码器编码后等到一个几位二进制的数,怎么计算的?
    发表于 03-14 13:07

    Labview种如何将一个数字转换为5二进制,8二进制以及任意二进制表示呢

    Labview种如何将一个数字转换为5二进制,8二进制以及任意二进制表示呢
    发表于 01-22 17:22

    如何使用USART接收二进制

    我想制作一个以8个LED的形式实现二进制计数器。该计数器通过USART发送一个8二进制数,并让8个LED显示数字(如果位为0,则指示灯熄灭,当
    发表于 10-08 14:07

    labview编程模拟十进制数到二进制数的转换过程

    模拟十进制数到二进制数的转换过程,以LED来模拟各个二进制位,并能以动画方式模拟计数的过程。 选择手动方式时,将8个LED变成滑动条中数字的二进制(基数2)表示。例如,如果滑动条设置为
    发表于 12-07 22:20

    如何理解二进制运算规则 二进制是如何运算的

    的数都是0)。小数部分也一样,但精确度较少。(2)二进制转换为八进制:采用“三一并法”(是以小数点为中心向左右两边以每三分组,不足的补上0)这样就可以轻松的进行转换。例:将
    发表于 12-11 17:49

    二进制转换64k为什么等于0x1000

    按照地址分配,64K图一用size等于0x10000? 计算转化所得0X10000=65536=2^16,也就是17个二进制位(bit)才对呀可是flash为64K,64K=65536个字节,一个字节=8个bit,应该是65536*8个bit(二进制位)才对。
    发表于 02-27 14:34

    二进制计数电子电位器CD4040电子资料

    概述:CD4040是一款二进制集成电路,用CD4040制作的电子电位器,电位可有4096挡次,如电压在4.096V,每伏有1000个1mV变化进位挡,每进1上升1mV,电路二进制位0~11
    发表于 04-07 07:00

    如何提高嵌入式跨平台的移植性与兼容性

    signed long。然后娓娓道来:显而易见,u就是unsigned的缩写,s就是signed的缩写,8就表示8个二进制位(一个字节),16就表示16个
    发表于 11-08 06:25

    浮点数转换为二进制存储的方法

    浮点数转换为二进制存储根据IEEE754标准,单精度float类型使用32比特存储,其中1表示符号,8表示指数,23表示尾数;双精度doubl
    发表于 12-09 06:09

    二进制逻辑运算详解

    二进制运行详解
    发表于 02-14 16:56 13次下载

    C语言编程二进制位操作符

    C语言编程二进制位操作符
    发表于 03-30 14:09 6次下载

    函数转换BCD编码二进制数为整型

    BCD码亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。它是一种二进制的数字编码形式,用
    的头像 发表于 03-14 10:15 6191次阅读