• 注册 / 登录
  • 切换到窄版
  • 查看: 2418|回复: 0

    C语言各数据类型的内存映像

    [复制链接]

    676

    主题

    690

    帖子

    6808

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6808
    发表于 2022-7-18 16:57:53 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

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

    3.png

    0signed char
    1. #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
    2.         {            printf("%c ",i);            if(i%32==0)                printf("\n%d ",i);
    3.         }
    4.     getchar();
    5. }
    复制代码

    output:

    4.png

    1、整型的signed和unsigned

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

    如果一个表达式同时包含signed和unsigned整型,signed会提升为unsgined,可能会隐藏一些意想不到的错误,特别是用在比较运算时:
    1.     unsigned int a=4294967290;    int b=-6;
    2.     printf("%d\n",a==b); // 1 , b promotes to unsigned
    复制代码

    2、double的二进制位显示

    1. #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));
    2. }int main(){    int n = 0x01020304;    if(*(char*)&n == 4)        printf("小端:");//小端:
    3.     double d = 15.75; // 1111.11, 指数位值:1023+3
    4.     //0 100 0000 0010 1111100000000000000000000000000000000000000000000000
    5.     printByte(d);//00 00 00 00 00 80 2F 40
    6.     // 40              2F               80
    7.     // 0100 0000 0010 1111 1000 0000
    8.     getchar();
    9. }
    复制代码

    将double分成4部分显示:

    1. #include <stdio.h>typedef struct packed_double {
    2.     unsigned int low32;    // 小数位 低32位
    3.     unsigned int low20:20; // 小数位 低33-52位
    4.     unsigned int exp11:11; // 指数位 低53-63位,移码1023+二进制整数位-1
    5.     unsigned int sign:1;  // 符号位} packed_double;typedef union {    double d;
    6.     packed_double b;
    7. } packed;int main(){
    8.     packed pd;
    9.     pd.d = -15.75;
    10.     pd.d = 12.3;    printf("%u %u %u %u\n",pd.b.sign,pd.b.exp11,pd.b.low20,pd.b.low32);
    11.     getchar();
    12.     return 0;
    13. }/*
    14. 0 1026 1015808 0
    15. */
    复制代码

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

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

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

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

    1. #include <stdio.h>int main(){    enum Nm{LOSS,TIE,WIN}nm; // 实质是一个整型,成员只是可能的右值(符号常量)的枚举
    2.     nm = LOSS;    printf("%d ",nm); // 0
    3.     nm = TIE;    printf("%d ",nm); // 1
    4.     nm = WIN;    printf("%d ",nm); // 2
    5.     nm = (enum Nm)3;  
    6.     printf("%d ",nm); // 3
    7.     printf("\n%d",sizeof(enum Nm)); // 4
    8.     getchar();
    9. }
    复制代码

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

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

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

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

    1. #include <stdio.h>#include <string.h>#define MAXPARTS 12struct Parts{ // 零件
    2.         int cost;        char supplier[12];        char unit[12] ;
    3. };struct Assembly{ // 装配件
    4.         int n_parts;        struct {
    5.                 char partno[12];
    6.                 short quan;
    7.         }parts[MAXPARTS];
    8. };struct Inventory{ // 存货类型,或是零件,或是装配件
    9.         char partno[10];        int quan;        enum{PART,ASSEMBLY}type; // 存货类型
    10.         union {                struct Parts parts;
    11.                 struct Assembly assembly;
    12.         }info;
    13. };int main(){        struct Inventory screen;
    14.         strcpy(screen.partno,"p001");
    15.         screen.quan = 12;
    16.         screen.type = Inventory::PART;
    17.         screen.info.parts.cost = 122;        strcpy(screen.info.parts.supplier,"hw");        strcpy(screen.info.parts.unit,"pcs");       
    18.         struct Inventory shell;
    19.         strcpy(shell.partno,"a001");
    20.         shell.quan = 4;
    21.         shell.type = Inventory::ASSEMBLY;
    22.         shell.info.assembly.n_parts=22;        strcpy(shell.info.assembly.parts[0].partno,"d001");
    23.         shell.info.assembly.parts[1].quan = 5;        int costs;        if(shell.type == Inventory::ASSEMBLY)
    24.                 costs = shell.info.assembly.n_parts;       
    25.         printf("%d\n",costs); //22
    26.         getchar();        return 0;
    27. }
    复制代码

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

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

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

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

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

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

    1. #include <stdio.h>void printBinM(unsigned int n){    for(int i=31;i>=0;i--)        printf("%d",(n & 1<<i)>>i);    printf("\n");
    2. }struct Bf{   
    3.     unsigned a:3;   
    4.     unsigned b:4;   
    5.     unsigned c:5;
    6. }bf;int main(){
    7.     bf.a =1;
    8.     bf.b=15;
    9.     bf.c=3;    int *p = (int*)&bf; // 505
    10.     printf("%d\n",*p);
    11.     printBinM(*p);//00000000000000000000000111111001
    12.     getchar();
    13. }
    复制代码

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

    1. #include <stdio.h>void printBinM(unsigned int n){    for(int i=31;i>=0;i--)        printf("%d",(n & 1<<i)>>i);    printf("\n");
    2. }int main(){    struct Bf{   
    3.         unsigned a:3;   
    4.         unsigned b:4;   
    5.         unsigned c:5;
    6.     }bf;
    7.     bf.a =1;
    8.     bf.b=15;
    9.     bf.c=3;    int *p = (int*)&bf; // -858996231
    10.     printf("%d\n",*p);
    11.     printBinM(*p);//11001100110011001100000111111001
    12.     getchar();
    13. }
    复制代码

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-12-22 15:04 , Processed in 0.048006 second(s), 21 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表