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

0 signed char

#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:

1 整型的signed和unsigned

#include <stdio.h>
int 
main
()

{

    signed int smin = 1<<31;

    signed int smax = (1<<31)-1;

printf
(
"%d\n"
,smin);    // -2147483648

printf
(
"%d\n"
,smax);    // 2147483647

    unsigned int umax = -1;

printf
(
"%u\n"
,umax);    // 4294967295

    umax = (1<<32)-1;

printf
(
"%u\n"
,umax);    // 4294967295

}

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

    int b=-6; 

printf
(
"%d\n"
,a==b); // 1 , b promotes to unsigned

2 double的二进制位显示

#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部分显示:
#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 %u\n"
,pd.b.sign,pd.b.exp11,pd.b.low20,pd.b.low32);

    getchar(); 

return
 0;

}

/*

0 1026 1015808 0

*/

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

数组名是一个存储数据首元素地址具有常量性质的特殊指针,成员是相对于基址的偏移:
#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 枚举只是枚举可以取值的一些符号常量的一个特殊整型

#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 共用体成员的起始地址相同,共用一块内存空间,值相互覆盖

#include <stdio.h>
int 
main
()

{

    union Nn{int a; double b;}nn;// 成员的起始地址相同,值相互覆盖

    nn.a = 123; // 

printf
(
"起始地址:%X,内存空间占用:%d\n"
,&nn.a,sizeof nn.a);

    nn.b = 12.3;

printf
(
"起始地址:%X,内存空间占用:%d\n"
,&nn.a,sizeof nn.b);

    nn.a = 12;

printf
(
"起始地址:%X,内存空间占用:%d\n"
,&nn.a,sizeof nn.a);

    getchar();

}

/*

起始地址:12FF40,内存空间占用:4

起始地址:12FF40,内存空间占用:8

起始地址:12FF40,内存空间占用:4

*/

当一些事物具有更多共性,但有少量差异时,可以只用一个内嵌一个共用体的结构体来描述:
#include <stdio.h>
#include <string.h>
#define MAXPARTS 12

struct 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\n"
,costs); //22

 getchar();

return
 0;

}

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

结构体各数据成员的引用可以通过其内存大小和字节对齐来相对于基址偏移来计算。结构体通常用于描述某一事物,用其成员来描述该事物的某些关键属性。让该事物既可以用结构体变量整体表示,也可以对其成员分别引用来处理该事物的各个属性。
#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 %d\n"
,abc.b,*p); // 12 12

printf
(
"%d\n"
,sizeof(struct demo));// 8

    getchar();

}

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

(一次可以处理n个位,1<=n<=整形长度)
位域(全局)二进制位显示:
#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
(
"%d\n"
,*p);

    printBinM(*p);//00000000000000000000000111111001

    getchar();

}

位域(局部)二进制位显示:
#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
(
"%d\n"
,*p);

    printBinM(*p);//11001100110011001100000111111001

    getchar();

}
来源:https://www.toutiao.com/article/7104201545675178528
- EOF -
↓推荐关注↓
「CPP开发者」在 Github 维护着 9000+ star 的C/C++开发资源。日常分享 C语言 和 C++ 开发相关技术文章,每篇文章都经过精心筛选,一篇文章讲透一个知识点,让读者读有所获~
点赞和在看就是最大的支持❤️
继续阅读
阅读原文