嵌入式第十六天

复习:
指针:
二级指针:
int a=12;
int *q=&a;
int **p;
p=&q;

*p **p p &p &q

数组指针:指针 

指针数组:数组 
int (*p)[3]
int *p[3]

局部变量
全局变量

static 
    局部变量 
    全局变量 
    函数 

extern
    全局变量 
    
函数:
int fun(int a,int b)//a=m b=n
{
    return a;
}
int main()
{
    int x=fun(m,n);
}

void void*

void * p;
void a;  
    
递归:
 栈空间
 
指针函数


一、函数指针:本质是指针 存函数地址 指向一类函数
函数指针3步:
    定义 
    赋值 
    调用

1.定义函数指针:根据函数定义函数指针
    int max()
    {

    }

    int min()
    {

    }

    int add()
    {

    }

    int (*p)();//定义函数指针p 可以指向返回值类型为int 没有形参的一类函数
    
2.赋值
    p=max;//将函数max的首地址 赋值给函数指针p
3.调用
    (*p)();//*p()也可以

    无参:
     #include<stdio.h>
    int max()
    {
        int a=90;
        int b=20;
        return a>b?a:b;
    }
    int main()
    {
        int (*p)()=NULL;
        p = max;
        int ret = (*p)();//max();
        printf("%d\n",ret);

        return 0;
    }
    
    有参:
    #include<stdio.h>
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    int main()
    {
        int c=90;
        int d=89;
        int (*p)(int,int)=NULL;
        p = max;
        int ret = (*p)(c,d);//max();
        printf("%d\n",ret);

        return 0;

    }
    
    练习:定义函数指针
    定义函数指针指向void *malloc(size_t size);
    void*(*pfun)(size_t);
    定义函数指针指向void fun()
    void (*p)();
    
    练习:定义一函数指针 指向一个函数 函数功能:求两个数的和
    #include<stdio.h>
    void add(int a,int b)
    {
        printf("%d\n",a+b);
    }
    int main()
    {
        int c=90;
        int d=89;
        void (*p)(int,int)=NULL;
        p = add;
       (*p)(c,d);//max();
        return 0;
    }


    例子:
    #include<stdio.h>
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    int main()
    {
        int c=90;
        int d=89;
        int ret,choose;
        
        int (*p)(int,int)=NULL;
        
/*        
        p = max;
        ret = (*p)(c,d);//max();
        printf("%d\n",ret);
        
        p=min;
        ret = (*p)(c,d);//max();
        printf("%d\n",ret);
*/
        puts("1.max 2.min");
        scanf("%d",&choose);
        switch(choose)
        {
            case 1:
                p=max;
                break;
            case 2:
                p=min;
                break;
            default:
                puts("error!");
                break;        
        }        
        
        ret = (*p)(c,d);
        printf("%d\n",ret);

        return 0;
    }
    
    练习:函数指针版本-计算器 
    #include<stdio.h>
    #include<stdlib.h>
    void add(int a,int b)
    {
        printf("%d\n",a+b);
    }
    void sub(int a,int b)
    {
        printf("%d\n",a-b);
    }
    void mul(int a,int b)
    {
        printf("%d\n",a*b);
    }
    void _div(int a,int b)
    {
        printf("%d\n",a/b);
    }
    int main()
    {
        int choose;
        int x,y;

        void (*pfun)(int,int)=NULL;
        while(1)
        {
            puts("input op1 op2");
            scanf("%d%d",&x,&y);

            puts("1.add 2.sub 3.mul 4.div 5.exit");
            scanf("%d",&choose);
            switch(choose)
            {
                case 1:
                    pfun = add;
                    break;
                case 2:
                    pfun = sub;
                    break;
                case 3:
                    pfun = mul;
                    break;
                case 4:
                    pfun = _div;
                    break;
                case 5:
                    exit(0);//正常退出
                default:
                    puts("choose error!");
                    continue;
            }
            (*pfun)(x,y);
            sleep(1);
            system("clear");
        }
        return 0;

    }

4.函数指针做形参
    函数指针定义:函数调用时
    函数指针赋值:实参传递给形参时
    函数指针调用:函数体内
    例子1:
    #include<stdio.h>
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    void fun(int (*p)(int,int),int m,int n)//p=max  m=x n=y
    {
        
        int ret = (*p)(m,n);//-->max(x,y)
        printf("%d\n",ret);
    }
    int main()
    {
        int x=90;
        int y=89;
        fun(max,x,y);
    }

    例子2:
    #include<stdio.h>
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    int min(int a,int b)
    {
        return a<b?a:b;
    }

    int add(int a,int b)
    {
        return a+b;
    }
    void fun(int (*p)(int,int),int m,int n)//p=max  m=x n=y
    {
        
        int ret = (*p)(m,n);//-->max(x,y)
        printf("%d\n",ret);
    }
    int main()
    {
        int x=90;
        int y=89;
        fun(max,x,y);
        fun(min,x,y);
        fun(add,x,y);
    }

    练习:函数指针形参版本计算器
    #include<stdio.h>
    #include<stdlib.h>
    void add(int a,int b)
    {
        printf("%d\n",a+b);
    }
    void sub(int a,int b)
    {
        printf("%d\n",a-b);
    }
    void mul(int a,int b)
    {
        printf("%d\n",a*b);
    }
    void _div(int a,int b)
    {
        printf("%d\n",a/b);
    }

    void fun(void (*p)(int,int),int a,int b)
    {
        (*p)(a,b);
    }
    int main()
    {
        int choose;
        int op1,op2;
        while(1)
        {
            puts("input op1 op2");
            scanf("%d%d",&op1,&op2);

            puts("1.add 2.sub 3.mul 4.div 5.exit");
            scanf("%d",&choose);
            switch(choose)
            {
                case 1:
                    fun(add,op1,op2);
                    break;
                case 2:
                    fun(sub,op1,op2);
                    
                    break;
                case 3:
                    fun(mul,op1,op2);
                    break;
                case 4:
                    fun(_div,op1,op2);
                    break;
                case 5:
                    exit(0);//正常退出
                default:
                    puts("choose error!");
                    break;
            }
            sleep(1);
            system("clear");
        }
        return 0;

    }

5.函数指针数组:代替大型switch语句
    int (*p[2])(int,int);
    int (*p[2])(int,int)={max,min};
    p[0]=max;
    p[1]=min;
     
    #include<stdio.h>
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    int min(int a,int b)
    {
        return a<b?a:b;
    }


    int main()
    {
        int choose;
        int (*p[2])(int,int)={max,min};//p[0]->max  p[1]min  *p p[0]
        for(;;)
        {
            puts("1.max  2.min");
            scanf("%d",&choose);//1
            printf("%d\n",p[choose-1](3,7));
        }
    }

    练习:函数指针数组版本计算器
    #include<stdio.h>
    #include<stdlib.h>
    void add(int a,int b)
    {
        printf("%d\n",a+b);
    }
    void sub(int a,int b)
    {
        printf("%d\n",a-b);
    }
    void mul(int a,int b)
    {
        printf("%d\n",a*b);
    }
    void _div(int a,int b)
    {
        printf("%d\n",a/b);
    }

    int main()
    {
        void (*p[4])(int,int)={add,sub,mul,_div};
        int choose;
        int op1,op2;
        while(1)
        {
            puts("input op1 op2");
            scanf("%d%d",&op1,&op2);

            puts("1.add 2.sub 3.mul 4.div ");
            scanf("%d",&choose);
            p[choose-1](op1,op2);
            sleep(1);
            system("clear");
        }
        return 0;

    }

二、const:c语言关键字 用来定义一个常量
1.
#include<stdio.h>

int main()
{
    int const a=100;//定义一个常量a 其值为100
    a = 200;//因为a是常量 不可以被赋值
    printf("%d\n",a);
    return 0;

}
2.const和指针关系
(1)int const *p;//等价于const int *p
    #include<stdio.h>

    int main()
    {
        int a;
        a=100;
        
        int const *p=80;
        //p=&a;//可以 因为p是变量
        *p = 80;//错 因为*p是常量 不能放赋值符号左边
        printf("%d\n",*p);
        return 0;
    }

(2)int *const p;
    #include<stdio.h>

    int main()
    {
        int a;
        a=100;
        
        int *const p=&a;
        //p=&a;//错 因为p是常量 不能放赋值符号左边
        *p = 80;//可以 
        printf("%d\n",*p);
        return 0;
    }
(3)int const *const p;//p和*p都是常量


三.宏定义:机械替换
(1)宏定义可以嵌套
    #define 宏名 宏值
    #define N 3 

    #include<stdio.h>
    #define N 2
    #define M N+1
    int main()
    {
        int a=M*M;//N+1*N+1=2+1*2+1=5
        printf("%d\n",a);//5
        return 0;
    }

(2)带参宏
    例子1:
    #include<stdio.h>
    #define SQUARE(x) x*x
    int main()
    {
        int a=SQUARE(3);
        printf("%d\n",a);//9
        return 0;

    }    
    例子2:    
    #include<stdio.h>
    #define SQUARE(x) x*x
    int main()
    {
        int a=SQUARE(2+3);//2+3*2+3=2+6+3=11
        printf("%d\n",a);//11
        return 0;
    }    
        
    应该是:
    #include<stdio.h>
    #define SQUARE(x) (x)*(x)
    int main()
    {
        int a=SQUARE(2+3);//2+3*2+3=2+6+3=11
        printf("%d\n",a);//11
        return 0;
    }    
    
    练习:实现一个宏MAX 能求两个数最大值 
    #define MAX(a,b) (a)>(b)?(a):(b)
    
    练习:定义一个宏 传入一个字符 如果是大写 转为小写 若是小写 则不变
    #include<stdio.h>
    #define TOS(x) (x)>='A'&&(x)<='Z'?((x)+32):(x)
    int main()
    {
        char ch;
        while(1)
        {
            ch=getchar();
            getchar();
            ch=TOS(ch);
            printf("%c\n",ch);
        }    
        return 0;

    }

    带参宏与函数调用区别:
    带参宏:编译阶段替换 运行效率高 但编译会导致代码量增大
    函数调用:运行时调用  

    代码量小 使用带参宏
    代码量大 函数调用 

四、条件编译(可以实现让某一部分代码参加编译或不参加编译)
1.#ifdef 标识符
   程序段
  #endif 

    #include<stdio.h>
    #define A 
    int main()
    {
    #ifdef A  //如果定义A 则下边的语句参加编译 否则不执行
    puts("hahahaha");//输出
    #endif
        return 0;

    }


    方法2:
    #include<stdio.h>
    int main()
    {
    #ifdef A
        puts("hahahaha");//输出
    #endif
        return 0;
    }
    gcc -D A y.c  //-D 带宏编译

2.#ifdef 标识符 //如果标识符已经定义 则编译程序段1 否则编译程序段2
    程序段1
  #else 
    程序段2 
  #endif
  
  #include<stdio.h>
    int main()
    {
    #ifdef A
    puts("hahahaha");
    #else 
    puts("heiheihei~");
    #endif
        return 0;

    }

3。#if 常量/常量表达式  //如果为真 则编译程序段 否则 不编译  主要用于调试程序
    程序段 
   #endif     

    #include<stdio.h>
    int main()
    {
    #if 1
        puts("pleaes input the num of stu:");
        puts("hahahaha");
    #endif
        puts("heiheihei~");

        return 0;

    }

4.#if 常量/常量表达式   //如果为真则编译程序段1 否则编译程序段2
  程序段1 
  #else 
  程序段2 
  #endif       

    #include<stdio.h>
    int main()
    {
    #if 0
        puts("pleaes input the num of stu:");
        puts("hahahaha");
    #else
        puts("heiheihei~");
    #endif
        return 0;

    }

5.自定义头文件
(1) 头文件:
    系统头文件<>
    自定义头文件""
    
    
    //y.h 
    #ifndef Y_H
    #define Y_H

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #endif

    //y.c 
    #include"y.h"
    int a=90;
    int main()
    {
        if(a>=90)
        {
            printf(">=\n");
            exit(-1);
        }
        return 0;
    }    
    gcc y.c 
    ./a.out


(2)头文件中条件编译作用:避免头文件重复包含
    //a.h 
    #ifndef A_H 
    #define A_H

    int max=100;

    #endif 
    //b.h 
    #include"a.h"

    //main.c 
    #include"a.h"  //int max=100;
    #include"b.h" 
    int main()
    {
        
    }
    
五、结构体大小-内存对齐
规则:
(1)数据成员对齐:第一个数据存放到相对结构体起始位置偏移为0的地址
(2)以后每个数据成员存储的起始位置从该成员大小的整数倍开始
(3)结构体大小 也就是sizeof的结果 必须是其内部最大成员与机器字长比较 
 按小的对齐  也就是结果是小的的整数倍 不足补齐
  
 机器字长:CPU一次能处理数据位数

(4)特殊情况 如果结构体作为成员 则存储要从其内部最大元素大小的整数倍开始存储
(5)设置对齐参数
 #include<stdio.h>
    struct  stu 
    {
        char a;
        short b;
        char c;
    };
    int main()
    {
        struct stu s1;
        printf("&s1.a:%p &s1.b:%p &s1.c:%p\n",&s1.a,&s1.b,&s1.c);
        printf("%d\n",sizeof(s1));//6
        return 0;
    }
    &s1.a:0xbfc88aaa &s1.b:0xbfc88aac &s1.c:0xbfc88aae
    0 1 2 3 4 5 6 7 8 
    a   b 


    #include<stdio.h>
    struct  stu 
    {
        char a;
        short b;
        char c;
        short d;
    };
    int main()
    {
        struct stu s1;
        printf("&s1.a:%p &s1.b:%p &s1.c:%p\n",&s1.a,&s1.b,&s1.c);
        printf("%d\n",sizeof(s1));//8
        return 0;
    }
    
    #include<stdio.h>
    struct s
    {
        double f;
        char ch;
    };
    int main()
    {
        printf("%d\n",sizeof(struct s));//12
    }
    
    #include<stdio.h>
    #pragma pack(3)   //#pragma pack(n) n表示c编译器将按照n个字节对齐  n必须是2的次方
    struct s
    {
        int f;
        char ch;
    };
    int main()
    {
        printf("%d\n",sizeof(struct s));//6
    }
    
    练习: 
    struct p 
    {
        char a;
        int b;
        char c 
    }
    
    struct q 
    {
        char ch;
        struct p class;
    }
    
    sizeof(q) 12 
    
    
    
        
    


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值