我是靠谱客的博主 会撒娇茉莉,这篇文章主要介绍C语言各数据类型的内存映像2、double的二进制位显示3、数组是相同数据类型的依次存储4、枚举只是枚举可以取值的一些符号常量的一个特殊整型5、共用体成员的起始地址相同,共用一块内存空间,值相互覆盖6、结构体是不同数据类型的数据依次存储在一起7、位域是对整型数据的按位处理,现在分享给大家,希望可以做个参考。

    关注、星标公众号,直达精彩内容

ae0504db2b928a6cb1f7d5827aa55d2f.png

来源:网路素材

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

865e58ef94e8588732f48e630f068791.png

0、signed char

复制代码
1
2
3
4
5
#include <stdio.h>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("n%d ",i); } getchar(); }

output:

32bdc22a831578a34c84c1b8c004b4da.png

1、整型的signed和unsigned

复制代码
1
2
3
4
#include <stdio.h>int main(){ signed int smin = 1<<31; signed int smax = (1<<31)-1; printf("%dn",smin); // -2147483648 printf("%dn",smax); // 2147483647 unsigned int umax = -1; printf("%un",umax); // 4294967295 umax = (1<<32)-1; printf("%un",umax); // 4294967295}

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

复制代码
1
2
unsigned int a=4294967290; int b=-6; printf("%dn",a==b); // 1 , b promotes to unsigned

2、double的二进制位显示

复制代码
1
2
3
4
5
6
7
8
9
#include <stdio.h>void printByte(double d){ int bs = sizeof d; unsigned char *ch = (unsigned char*)&d; for(int i=0;i<bs;i++) printf("%.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部分显示:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>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 %un",pd.b.sign,pd.b.exp11,pd.b.low20,pd.b.low32); getchar(); return 0; }/* 0 1026 1015808 0 */

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

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

复制代码
1
2
3
4
5
6
7
#include <stdio.h>void printArr(short arr[],int len){ for(int i=0;i<len;i++) { printf("%d ",*(arr+i)); } printf("n"); }int main(){ short arr[] = {1,3,2}; int len = sizeof arr / sizeof *arr; printArr(arr,len); }

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

复制代码
1
2
3
4
5
6
7
8
9
#include <stdio.h>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("n%d",sizeof(enum Nm)); // 4 getchar(); }

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>int main(){ union Nn{int a; double b;}nn;// 成员的起始地址相同,值相互覆盖 nn.a = 123; // printf("起始地址:%X,内存空间占用:%dn",&nn.a,sizeof nn.a); nn.b = 12.3; printf("起始地址:%X,内存空间占用:%dn",&nn.a,sizeof nn.b); nn.a = 12; printf("起始地址:%X,内存空间占用:%dn",&nn.a,sizeof nn.a); getchar(); }/* 起始地址:12FF40,内存空间占用:4 起始地址:12FF40,内存空间占用:8 起始地址:12FF40,内存空间占用:4 */

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>#include <string.h>#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("%dn",costs); //22 getchar(); return 0; }

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

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

复制代码
1
2
3
4
5
6
7
#include <stdio.h>int main() { struct demo{char a; short b;int c;} abc; // 成员相对于基址偏移,字节对齐 abc.b=12; short *p = (short*)((int)&abc+sizeof(short)); // 模拟编译器计算第2个成员的偏移地址 printf("%d %dn",abc.b,*p); // 12 12 printf("%dn",sizeof(struct demo));// 8 getchar(); }

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

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>void printBinM(unsigned int n){ for(int i=31;i>=0;i--) printf("%d",(n & 1<<i)>>i); printf("n"); }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("%dn",*p); printBinM(*p);//00000000000000000000000111111001 getchar(); }

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>void printBinM(unsigned int n){ for(int i=31;i>=0;i--) printf("%d",(n & 1<<i)>>i); printf("n"); }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("%dn",*p); printBinM(*p);//11001100110011001100000111111001 getchar(); }

版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

复制代码
1
关注我的微信公众号,回复“加群”按规则加入技术交流群。
复制代码
1
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

最后

以上就是会撒娇茉莉最近收集整理的关于C语言各数据类型的内存映像2、double的二进制位显示3、数组是相同数据类型的依次存储4、枚举只是枚举可以取值的一些符号常量的一个特殊整型5、共用体成员的起始地址相同,共用一块内存空间,值相互覆盖6、结构体是不同数据类型的数据依次存储在一起7、位域是对整型数据的按位处理的全部内容,更多相关C语言各数据类型内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部