数据结构——结构体位域、typedef类型重定义、宏、共用体union、枚举、虚拟内存划分

一、结构体位域

  1.1 结构体位域的基础

结构体位域:把结构体字节大小扣到极致的一个类型,以bit单位

格式:
 struct 位域体名
 {
     数据类型 位域名:位域大小;
      数据类型 位域名:位域大小;
      ...
 };
 解析:
 位域体名:可有可无,满足命名规范
 数据类型:只能是整数(char\short\int\long\long long)
 位域名:可有可无,如果不屑,则默认该位不可以使用,结果位0
 位域大小:不可以大于数据类型的总位值
 eg:
     struct A
     {
        int a:10;
        int b:20;
        char c:6;
        ...       
     };
      struct B
     {
        int a:10;
        int :20; //20位不可以使用,默认是0
        char c:6;
        ...       
     };

  1.2 结构体位域的大小

1.结构体位域的各个数据类型一致,且总和小于最宽数据类型的字节大小
  分配字节单位是以最宽数据类型字节大小分配
    struct A
    {
        int a:2;
        int b:3;
        int c:20;    
    };
    结构体分配最宽成员的字节大小,int---->32
    a:2  剩余30bit,  b:3 剩余27  c:20 剩余7位
    共4字节
  2.结构体位域的各个数据类型一致,且总和大于最宽数据类型的字节大小
      不可以跨字节存储
    struct B
    {
        int a:20;
        int b:23;
        int c:7;    
    };
    最宽数据类型int--->32bit
    a:20 剩余12,  b:23不够存储,则需要重新申请4字节存储b
    b:23  剩余9   c:7  剩余2
    共8字节
    3.结构体位域的各个数据类型不一致,且总和大于最宽数据类型的字节大小
        struct C
    {
        char a:7;
        short b:15;
        int c:30;
        long d:20;
        long long e:53;
    };
    最宽long long -->8字节---》64bit
    a:7  剩余57  b:15:42  c:30  剩余12   d:20  重新8字节, 
    剩余44    e:53  重新申请8字节 
    共24字节

  1.3 结构体位域的使用

struct C
    {
        char a:7;   -2^6  2^6-1
        short b:15;  -2^14   2^14-1
        int c:30;    -2^29   2^29-1
        unsigned long d:20;
        long long e:53;
    };
    struct C num={128,20,30,40,50};
    printf("%d",num.a);
   
   char  -128,127
   char a=128  --->a=-128
   char b=129  --->b:-127
   char c=130   --->c:-126
   
   如果数据在赋值时出现数据溢出,则会从最大值到最小值上

二、typedef类型重定义

typedfef: 类型重定义

格式: typedef 数据类型 别名;

1.typedef: 类型重定义

2.数据类型:基类型,构造类型,空类型,指针类型

3.别名:满足命名规范

size_t 在64操作系统unsigned long 32操作系统unsigned int

typedef int size_4; //把int起别名size_4 int--->sise_4

int a;--->size_4 a;

typedef unsigned long size_t;

typedef unsigned int size_t;


    int age;
    char name[100];
}p_t;

方式1:
struct Person a;
typedef struct Person p_t; //struct Person起别名p_t
p_t a;


int a;
int arr[2];
int *p;

typedef int a,arr[2],*p;   a-->int   arr-->int[2]  p-->int*

typedef int a;
typedef float a;
C语言变量
int a;
int arr[3];
int arr[2][3];
int* p;
int** p;
int (*p)[3];
int *p[3]
int (*p)();
int *p()
C类型
int ;
int [3];
int [2][3];
int* ;
int** ;
int (*)[3];
int *[3]
int (*)();
int *()
typedef和类型的结合
typedef int a_t;//a_t类型别名,表示int
typedef int arr_t[3] ;//arr_t类型别名,表示int [3]
    int arr[3]--->arr_t b;
typedef int arr_t[2][3];
typedef int* p_t;
typedef int** p_t;
typedef int (*p_t)[3];
typedef int *p_t[3]
typedef int (*fun_t)();
typedef int *fun_t();

eg:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])               
{
    typedef int size_4;
    size_4 a=100;
    printf("a=%d\n",a);
    
    typedef  int arr_t[2][3];//arr_t等价int [2][3];
    arr_t b={1,2,3,4,5,6};
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
            printf("%d\t",b[i][j]);
        putchar(10);
    }
    
    return 0;
}

三、宏

宏:宏只做替换,不做计算,不做正确性的检测

宏发生在预处理阶段

3.1 简单宏

格式:#define 宏名 宏体

1.#define 定义宏

2.宏名:满足命名规范,一般大写

3.宏体:默认时字符串

4.宏是没有类型,不需要在最后加;宏不是C语句

5.宏默认是全局,一般定义在主函数的上面

#define A 100
#deifne PAI  3.14
#define CH 'a'
#define STRING "hello"
#define size_4 int  size_4的值int

  3.2 宏函数

    3.2.1 自定义宏函数

1.({})

格式:
#define 宏函数名(参数列表) ({C语句1;C语句2...C语句n})
解析:
1.参数列表:没有数据类型,多个参数之间使用逗号隔开
2.({}):当C语句只有一条时默认可以省略不写
3.({}): 默认存在返回,返回最后一个表达式
4.宏体建议只写一行,换行需要使用\链接父,进行连接

eg:使用宏计算两个数的最大值
#define MAX1(x,y) x>y?x:y

#define MAX(x,y) ({int max;\
        if(x>y)\
        max=x;\
        else \
            max=y;\
        max;})                          
int main(int argc, const char *argv[])
{
    int a=11,b=22;
    int max=MAX(a,b);
    a>b?a:b;
    printf("max=%d\n",max);
    printf("max1=%d\n",MAX1(a,b));
    return 0;
}

2. do{}while(0)

格式:
    #define 宏函数名(参数列表) do{C语句1;C语句2....}while(0)
1.参数列表:没有数据类型,多个参数之间使用逗号隔开
2.do{}while(0) 后面不加分号
3.默认不存在返回
4.宏体建议只写一行,换行需要使用\连接符,进行连接
eg:使用宏计算两个数的最大值
#define MAX(x,y) do{if(x>y)printf("%d",x);else printf("%d",y);}while(0)

    3.2.2 系统自带的宏函数

1.判断宏是否为真,多用注释
    #if 宏名
        C语句1;
    #endif
执行过程:如果宏为真,则执行C语句,否则跳过
2.宏的双分支
    #if 宏名
        C语句1;
    #else
        C语句2;
    #endif
执行流程:如果宏为真则执行C语句1,否则执行C语句2
3.宏的多分支
    #if 宏名1
            C语句1;
    #elif 宏名2
            C语句2;
    ....
    #else
        C语句n;
    #endif
执行流程:如果宏1为真则执行C语句1,结束
    如果宏1为假,则判断宏2,如果宏2为真,则执行C语句2,结束
    以此类推
4.判断宏已经定义
    #ifdef 宏
        C语句1;
        C语句2;
    #endif
执行流程:判断宏已经定义了,如果定义了,则执行C语句
5.判断宏没有定义
    #ifndef 宏
        C语句1;
    #endif
执行流程:判断宏没有定义了,如果没有定义,则执行C语句  
6.判断多个宏已经定义
    #if defined(宏1) &&defined(宏2)
        C语句1;
    #endif
执行流程:判断宏已经定义了,如果定义了,则执行C语句
7.判断多个宏没有定义
    #if !defined(宏)    #if undefined==宏
        C语句1;
    #endif
执行流程:判断宏没有定义了,如果没有定义,则执行C语句    
8.# 把宏体转换为字符串
    #define FUN(a) #a
9,## 连接
    #define FUN(a,b) a##b

#讲解案例:

##的讲解案例:

    3.2.3 多文件编译

1.头文件:预处理命令,全局变量,头文件,函数生命

2.main函数

3.自定义函数

#include <>: 默认在系统库中查找头文件 库路径是/usr/include/

#include "":现在当前目录下查找头文件,找不到则在系统库中查找

  3.3 宏和typedef之间的区别

1.宏发生在预处理阶段,typedef 编译阶段

2.宏不是C语句,typedef是C语句

3.宏属于替换,typedef类型重定义

4.宏只能做基类型的简单替换,typedef可以重定义任何类型

typedef int size_4 typedef int arr[2]

#define size_4 int

四、共用体union

  4.1 认识共用体的格式

union 共用体名
{

 数据类型 变量名;
 数据类型 变量名;
 ····   
};   //定义了一个结构体类型

  4.2 共用体的地址

各个成员变量共享同一片空间

共用体字节大小等于最宽成员的字节大小,满足字节对齐原则

  4.3 共用体的使用

1.当没有指定成员时,默认给第一个成员赋值
typedef union A
{
    int a;
    char b;
    float c;
}A_t;
A_t num={100};   默认给第一个成员a赋值
2.指定成员赋值
A_t num2={.c=3.14};
3.定义变量后赋值
A_t num3;
num3.a=100;
num3.b='a';
num3.c=3.14
此时最终结果是最后一次赋值的结构

  4.4 使用union解决大小端存储

typedef union A
{
    int a;
    char b;
}A_t;
A_t num={0x12345678}
if(num.b==0x78)
    printf("little\n");
else
    printf("big\n");

五、枚举

  5.1 枚举的概念

枚举:防止魔鬼数字

枚举:列举所有集的有序序列的常量集合

枚举属于基类型

#define A 1

#define B 2

#define C 3

enum 枚举名
{
    变量名1,变量名2,....
};
1.enum:枚举关键字
2.枚举名:满足命名规范
3.变量名:没有数据类型,类型是自定义的枚举类型  enum 枚举名

  5.2 枚举的使用

1.默认没有赋值
enum NUM
{
    A,B,C   A默认结果是0,后面的一次递增 
};
printf("A=%d\n",A);
2.指定赋值
enum NUM
{
    A,B=50,C   A默认结果是0,B=50  C=51
};
enum NUM
{
    A=20,B=50,C=31   A默认结果是20,B=50  C=31
};
3.枚举变量
enum NUM
{
    A=20,B=50,C=31   A默认结果是20,B=50  C=31
};
enum NUM a=100;   //a是枚举变量,可以修改,ABC成员不可以修改

六、虚拟内存划分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值