2023年的C基础笔记

头介绍

#include 
#include 
#include 
// <> 寻找系统的资源
// “” 寻找我们自己写的资源
// .h .hpp(声明文件 头文件)
// .c  .cpp (实现文件)

基本数据类型的占位符

 int i = 100;
    double d = 200;
    float f = 200;
    long l = 100;
    short s = 100;
    //char类型
    char c = 'd';
    //char *  字符串类型
    char * str = "Derry";

    %d  d ==int 整形的占位符
    %lf  lf == long float 的占位符  
    %f  f == float 类型占位符          
    %c  c == char 类型占位符            
    %s  s == String类型占位符

  %p == 输出某某的(指针)地址 的占位符 

  概念

 数值==数字==实体建筑房子(可以一样重复)

 指针 == 地址==存放内存地址==指针地址==家庭的门牌号邮寄地址(唯一的)

 

    int  i = 100;
    int* ip=&i;
  & = 取出某某的(指针)地址=内存指针地址ip=&i=0061FF18     

 int  i = 100;
    printf("输出i的数值是:%d\n", i);// 输出i的数值是:100
    printf("输出i的内存指针地址是=%p\n", &i); // 输出i的内存指针地址是=0061FF18
    printf("输出i的数值是:%d\n", *(&i)); // 输出i的数值是:100

    int* ip=&i;
    printf("输出i的内存指针地址是=%p\n", ip);  //  输出i的内存指针地址是=0061FF18

  

   *  获取 某某的(指针)地址 的所对应的数值
   *(指针地址)      取出 某某的(指针)地址的 所对应的数值

    int  i = 100;
    int* ip=&i;
    *ip=666;

   数值i=*ip=*(&i)=666=内存指针地址ip的对应的数值

 int number_int = 100;
 int*  intP = &number_int;
//*  获取 某某的(指针)地址 的所对应的数值
    // *(指针地址)      取出 某某的(指针)地址的 所对应的数值
    printf("number_int的(指针)地址的所对应的数值是:%d\n", *(&number_int)); // number_int的(指针)地址的所对应的数值是:100
     // *(指针地址)    取出 某某的(指针)地址的 所对应的数值
    printf("number_int的(指针)地址的所对应的数值是:%d\n", *(intP));  //number_int的(指针)地址的所对应的数值是:100

 // C语言不支持函数重载, 要先声明函数 不能写在 main的下面,会报错. 参数pInt是个指针地址
void change(int* pInt);


int mainT7(){

    int  i = 100;
    printf("输出i的数值是:%d\n", i);// 输出i的数值是:100
    printf("输出i的内存指针地址是=%p\n", &i); // 输出i的内存指针地址是=0061FF18
    printf("输出i的数值是:%d\n", *(&i)); // 输出i的数值是:100

    int* ip=&i;
    printf("输出i的内存指针地址是=%p\n", ip);  //  输出i的内存指针地址是=0061FF18
    change(ip);
    printf("再次输出i的内存指针地址是=%p\n", ip); //再次输出i的内存指针地址是=0061FF18
    printf("再次输出i的数值是:%d\n", i); //再次输出i的数值是:666
    printf("再次输出i的数值是:%d\n",  *ip); // 再次输出i的数值是:666
    printf("再次输出i的数值是:%d\n", *(&i)); // 再次输出i的数值是:666

    //todo 综上可知: 内存指针地址ip=&i=0061FF18
    //todo 综上可知: 数值i=*ip=*(&i)=666=内存指针地址ip的对应的数值
    return 0;
}


// 再实现change函数 参数pInt 是个内存指针地址    写在 main的下面
void change(int* pInt){
    printf("change函数的参数pInt内存指针地址是=%p\n", pInt); // change函数的参数pInt内存指针地址是=0061FF18
    //修改内存指针地址pInt的对应的数值*pInt = 666=*(&i)
    *pInt=666;

}

       int number_int = 100;

      int*  intP = &number_int;

     int*   double*   叫 指针地址的类型
     intP,  doubleP  指针地址的变量名称   也叫 指针地址的变量别名/指针地址的变量/指针变量
     &number_int     number_int的(指针)地址

    // int*   double*   叫 指针地址的类型
    //  intP,  doubleP  指针地址的变量名称   也叫 指针地址的变量别名/指针地址的变量/指针变量
    //  &number_int     number_int的(指针)地址
    int number_int = 100;
    printf("number_int的值是:%d\n", number_int); //number_int的值是:100
    // &   某某的(指针)地址
    printf("number_int的(指针)地址是:%p\n", &number_int); //number_int的(指针)地址是:0061FF1C
 int*  intP = &number_int;
    printf("number_int的(指针)地址是:%p\n", intP);   // number_int的(指针)地址是:0061FF18

多级指针

多级指针:指针内存地址本身它自己在内存里也还个指针地址
 数值的指针内存地址
 数值的指针内存地址的  指针内存地址
 数值的指针内存地址的  指针内存地址 的指针内存地址
 数值的指针内存地址的  指针内存地址 的指针内存地址 的指针内存地址
 ......

 int num = 999;
 int * num_p = # // 一级指针 *  :  num_p = 数值num的指针地址
 int**  num_p_p = &num_p;  // 二级指针** : num_p_p = 一级指针num_p的 指针地址
 int *** num_ppp = &num_p_p; // 三级指针*** : num_ppp = 二级指针num_p_p的  指针地址

int main(){
    int num = 999;
    // 一级指针 *  :  num_p = 数值num的指针地址
    int * num_p = #
    printf("数值num的指针地址(即一级指针 *)num_p=%p\n",num_p); // 数值num的指针地址(即一级指针 *)num_p=0061FF18

    // 二级指针** : num_p_p = 一级指针num_p的 指针地址
    int**  num_p_p = &num_p;
    printf("一级指针num_p的 指针地址(即二级指针**)num_p_p=%p\n",num_p_p);// 一级指针num_p的 指针地址(即二级指针**)num_p_p=0061FF14

    // 三级指针*** : num_ppp = 二级指针num_p_p的  指针地址
    int *** num_ppp = &num_p_p;
    printf("二级指针num_p_p的  指针地址(即三级指针***)num_ppp=%p\n",num_ppp);  // 二级指针num_p_p的  指针地址(即三级指针***)num_ppp=0061FF10


    printf("数值num的数值=%d\n",num); //数值num的数值=999
    printf("一级指针num_p所对应的数值*num_p=%d\n",*num_p); // 一级指针num_p所对应的数值*num_p=999
    printf("二级指针num_p_p所对应的数值**num_p_p=%d\n",**num_p_p); // 二级指针num_p_p所对应的数值**num_p_p=999
    printf("三级指针num_ppp所对应的数值***num_ppp=%d\n",***num_ppp);// 三级指针num_ppp所对应的数值***num_ppp=999
  return 0;
}

 数组arr的内存地址

     int arr[]  = {10,20,30,40};
     数组arr自身就是一个内存地址arr==数组arr的内存地址&arr == 第一个元素arr[0]的内存地址&arr[0]=0061FF0C
     数组自身内存地址==arr=&arr=&arr[0]=0061FF0C
     反推数值:  *arr=*arr_p=*(&arr[0])=10

    
     数组arr的内存地址
    数组的第一个元素值i=10,元素值10的内存地址=0061FF0C
    数组的第二个元素值i=20,元素值20的内存地址=0061FF10
    数组的第三个元素值i=30,元素值30的内存地址=0061FF14
    数组的第四个元素值i=40,元素值40的内存地址=0061FF18
    
    
      数组的指针地址arr往后挪动i个位置  : arr_p = arr_p +i     
      数组的指针arr地址往前挪动i个位置: arr_p =arr_p -i  
     int* arr_p = arr;
     数组arr自身就是一个内存地址== 第一个元素arr[0]的内存地址&arr[0]=0061FF0C
     数组arr的内存地址arr_p所对应的数值*arr_p=10=元素一内存地址&arr[0]所对应的数值*(&arr[0])=10
    
    arr_p =arr_p+1;
    指针地址移动到下一个==元素二的内存指针地址=0061FF10
    数值arr的第二个元素的内存地址的所对应的数值*arr_p=20=元素二内存地址&arr[1]所对应的数值*(&arr[1])=20
    
    
    arr_p=arr_p+2;
    当前arr_p是第二个元素的内存指针地址,往下移动二个==元素四的内存指针地址=0061FF18
    数值arr的第四个元素的内存指针地址的所对应的数值*arr_p=40=元素四内存地址&arr[3]所对应的数值*(&arr[3])=40

     arr_p=arr_p-3;
     当前arr_p是第四个元素的内存指针地址,往前移动三位==元素一的内存指针地址=0061FF0C
     当前指针地址arr_p所对应的数值*arr_p=10=元素一内存地址&arr[0]所对应的数值*(&arr[0])=10
   

int main(){

    // 定义数组
    // int [] arr = {1,2,3,4}; 错误的写法
    int arr[]  = {10,20,30,40};

    
    // Linux上没有问题,Clion没有问题,Mac没有问题
    int i = 0;
    for (i = 0; i < 4; ++i) {
        printf("输出数组的每个元素值i=%d,元素值%d的内存地址=%p\n", arr[i],arr[i],&arr[i]);
    }

    /*
     输出数组的每个元素值i=10,元素值10的内存地址=0061FF0C
输出数组的每个元素值i=20,元素值20的内存地址=0061FF10
输出数组的每个元素值i=30,元素值30的内存地址=0061FF14
输出数组的每个元素值i=40,元素值40的内存地址=0061FF18
     */

     // todo 数组arr的内存地址
    // todo 数组arr自身就是一个内存地址arr==数组arr的内存地址&arr == 第一个元素arr[0]的内存地址&arr[0]=0061FF0C
    //todo 数组自身内存地址==arr=&arr=&arr[0]=0061FF0C

    printf("数组arr本身自己就是一个内存地址ar=%p\n", arr);//数组arr本身自己就是一个内存地址arr=0061FF0C
    printf("数组arr的内存地址&arr=%p\n", &arr); //数组arr的内存地址&arr=0061FF0C
    printf("数组arr的第一个元素arr[0]的内存地址&arr[0]=%p\n", &arr[0]); // 数组arr的第一个元素arr[0]的内存地址&arr[0]=0061FF0C


    //todo ======================================================================
    //todo 反推数值:  *arr=*arr_p=*(&arr[0])=10

    //todo 数组arr自身就是一个内存地址== 第一个元素arr[0]的内存地址&arr[0]
    int* arr_p = arr;
    printf("数组自身的内存地址arr所对应的数值*arr=%d\n",*arr); //数组arr自身的内存地址所对应的数值*arr=10
    printf("数组arr的内存地址arr_p所对应的数值是*arr_p=%d\n",*arr_p); //数组arr的内存地址arr_p所对应的数值是*arr_p=10

    printf("取出数组arr的内存地址arr_p所对应的数值*arr_p=%d=元素一内存地址&arr[0]所对应的数值*(&arr[0])=%d\n",*arr_p,*(&arr[0]));
    //取出数组arr的内存地址arr_p所对应的数值*arr_p=10=元素一内存地址&arr[0]所对应的数值*(&arr[0])=10

    //todo 指针地址移动到下一个==元素二的内存指针地址
     arr_p =arr_p+1;
    printf("取出数值arr的第二个元素的内存地址的所对应的数值*arr_p=%d=元素二内存地址&arr[1]所对应的数值*(&arr[1])=%d\n",*arr_p,*(&arr[1]));
   // 取出数值arr的第二个元素的内存地址的所对应的数值*arr_p=20=元素二内存地址&arr[1]所对应的数值*(&arr[1])=20

    //todo 当前arr_p是第二个元素的内存指针地址,往下移动二个==元素四的内存指针地址
    arr_p=arr_p+2;
    printf("取出数值arr的第四个元素的内存指针地址的所对应的数值*arr_p=%d=元素四内存地址&arr[3]所对应的数值*(&arr[3])=%d\n",*arr_p,*(&arr[3]));
      // 取出数值arr的第四个元素的内存指针地址的所对应的数值*arr_p=40=元素四内存地址&arr[3]所对应的数值*(&arr[3])=40

   //todo  当前arr_p是第四个元素的内存指针地址,往前移动三位==元素一的内存指针地址
   arr_p=arr_p-3;
   printf("输出当前指针地址arr_p所对应的数值*arr_p=%d=元素一内存地址&arr[0]所对应的数值*(&arr[0])=%d\n",*arr_p,*(&arr[0]));
  // 输出当前指针地址arr_p所对应的数值*arr_p=10=元素一内存地址&arr[0]所对应的数值*(&arr[0])=10

    // todo 当前arr_p是第一个元素的内存指针地址,往下移动2000位
    arr_p=arr_p+2000;
    printf("当前指针地址arr_p往下移动2000位后生成的新的指针地址arr_p,所对应的数值*arr_p=%d",*arr_p);
   //  当前指针地址arr_p往下移动2000位后生成的新的指针地址arr_p,所对应的数值*arr_p=572662306  是个系统值
    return 0;
}

使用指针遍历数组  2T4


需要指针地址arr_p随着数组的遍历循环+i=下一个指针的地址位置arr_p+i
数组是连续的内存空间(没有断层,有规律) int数组每次挪动 4个字节

// 4.使用指针遍历数组。
//需要指针地址arr_p随着数组的遍历循环+i=下一个指针的地址位置arr_p+i
int mainT24() {
    // todo 数组是连续的内存空间(没有断层,有规律) int数组每次挪动 4个字节

    // 定义数组
    // int [] arr = {1,2,3,4}; 错误的写法
    int arr[]  = {10,20,30,40};


    //数组arr的内存地址 arr_p=数组arr的第一个元素的内存地址&arr[0]
    int* arr_p=arr;

     //遍历数组
    int i=0;
    for(i = 0; i < 4; ++i){
        printf("位置%d的元素数值%d的内存地址=%p\n",i,*(arr_p+i),(arr_p+i));
        printf("位置%d的元素数值=%d\n",i,*(arr_p+i));
    }

  /**
位置0的元素数值10的内存地址=0061FF08
位置0的元素数值=10
位置1的元素数值20的内存地址=0061FF0C
位置1的元素数值=20
位置2的元素数值30的内存地址=0061FF10
位置2的元素数值=30
位置3的元素数值40的内存地址=0061FF14
位置3的元素数值=40

   */

    return 0;
}

循环时给数组赋值


   数组每个元素的内存地址 arr_p + i
   数组每个元素的内存地址所对应的数值  * (arr_p + i)
   遍历循环数组arr时 给数组的每个元素的内存地址arr_p+i  所对应的旧的数值*(arr_p+i)赋新的数值1000+i  

   即*(arr_p+i)=1000+i
    元素0的内存地址0061FF08所对应的赋值了新的数值=1000
    元素1的内存地址0061FF0C所对应的赋值了新的数值=1001
    元素2的内存地址0061FF10所对应的赋值了新的数值=1002
    元素3的内存地址0061FF14所对应的赋值了新的数值=1003

数组的长度

int类型的数组arr的长度 = sizeof arr  / sizeof(int)=16/4=4

int mainT25() {
    // 定义数组
    // int [] arr = {1,2,3,4}; 错误的写法
    int arr[]  = {10,20,30,40};

    //定义数值arr的内存指针地址 =第一个元素的内存地址
    int* arr_p=arr;

    // 循环赋值操作
    int i=0;
    for(i=0;i<4;++i){
        // 1.输出 元素一 元素二 元素三 元素四 的内存地址   (arr_p + i)
       printf("元素%d的内存地址=%p\n",i,(arr_p+i));
        // 2.输出 元素一 元素二 元素三 元素四 的内存地址 所对应的值 * (arr_p + i)
     printf("元素%d的内存地址%p所对应的原来数值=%d\n",i,(arr_p+i),*(arr_p+i));
    //todo 给数组的每个元素的内存地址arr_p+i  所对应的旧的数值*(arr_p+i)赋新的数值1000+i
     //元素0的内存地址0061FF08所对应的赋值了新的数值=1000
     //元素1的内存地址0061FF0C所对应的赋值了新的数值=1001
     //元素2的内存地址0061FF10所对应的赋值了新的数值=1002
     //元素3的内存地址0061FF14所对应的赋值了新的数值=1003
      *(arr_p+i)=1000+i;
      printf("元素%d的数值赋值后,元素%d的内存地址%p所对应的赋值了新的数值=%d\n",i,i,(arr_p+i),*(arr_p+i));
    }

/**
 元素0的内存地址=0061FF08
元素0的内存地址0061FF08所对应的原来数值=10
元素0的数值赋值后,元素0的内存地址0061FF08所对应的赋值了新的数值=1000
元素1的内存地址=0061FF0C
元素1的内存地址0061FF0C所对应的原来数值=20
元素1的数值赋值后,元素1的内存地址0061FF0C所对应的赋值了新的数值=1001
元素2的内存地址=0061FF10
元素2的内存地址0061FF10所对应的原来数值=30
元素2的数值赋值后,元素2的内存地址0061FF10所对应的赋值了新的数值=1002
元素3的内存地址=0061FF14
元素3的内存地址0061FF14所对应的原来数值=40
元素3的数值赋值后,元素3的内存地址0061FF14所对应的赋值了新的数值=1003
 */


  // todo int类型的数组arr的长度 = sizeof arr  / sizeof(int)=16/4=4
    printf("数组arr的长度=%d\n", sizeof arr / sizeof(int));// 数组arr的长度=4
    printf("输出 sizeof arr=%d\n", sizeof arr);  //输出 sizeof arr=16
   printf("输出 sizeof(arr)=%d\n", sizeof(arr));  // 输出 sizeof(arr)=16
    printf("输出 sizeof(int)=%d\n", sizeof(int)); //输出 sizeof(int)=4


    // 变量 刚刚赋值的数组
    for (int i = 0; i <  sizeof arr / sizeof(int); ++i) {
        printf("输出位置%d的新的数值是=%d\n", i, * (arr_p + i));
    }

  /**
输出位置0的新的数值是=1000
输出位置1的新的数值是=1001
输出位置2的新的数值是=1002
输出位置3的新的数值是=1003

   */


    return 0;
}

指针类型有何用  T27


指针占用的内存大小是?  int double char xxx类型的 的指针 永远都是   4个字节(32位)
指针类型有何用? 规定指针的类型是为了  计算指针的偏移量

/**
指针类型有何用
指针占用的内存大小是?  int double char xxx类型的 的指针 永远都是   4个字节(32位)
指针类型有何用? 规定指针的类型是为了  计算指针的偏移量
 */
int mainT27(){
    int num = 12;
    int* num_p = #
    printf("int类型的指针的占用内存的长度=%d\n",sizeof num_p); // int类型的指针的占用内存的长度=4

    double dou = 123.123;
    double* dou_p = &dou;
    printf("double类型的指针的占用内存的长度=%d\n",sizeof dou_p); //double类型的指针的占用内存的长度=4

   char cha='a';
   char* cha_p=&cha;
   printf("char类型的指针的占用内存的长度=%d\n",sizeof cha_p); // char类型的指针的占用内存的长度=4
   
   return 0;
};

函数指针1   T28


    函数本身就是一个指针地址
    add的函数指针地址 : add函数自身就是一个指针地址add=&add=00402022
    
    void(*method)(int,int)  函数指针的声明格式
    void 返回值
    (*method) 函数指针  method函数指针别名
    (int,int) 传递两个参数

void add(int num1, int num2); // 先声明
void mins(int num1, int num2) {
    printf("num1 - num2 = %d\n", (num1 - num2));
}


// void(*method)(int,int)  函数指针的声明格式
// void 返回值
// (*method) 函数指针  method函数指针别名
// (int,int) 传递两个参数
void opreate(void(*method)(int,int),int num1,int num2){
    //如果 形参函数指针method=实参函数指针add/&add
    // opreate函数的 形参method函数指针=00402022 =add=&add
    //如果 形参函数指针method=实参函数指针mins/&mins
    // opreate函数的 形参method函数指针=00401F10= mins=&mins
    method(num1, num2);
    printf("opreate函数的 形参method函数指针=%p\n", method);

}


//函数指针1  :函数本身就是一个指针地址
int mainT28(){
   add(1,2); //num1 + num2 = 3
   mins(3,2); // num1 - num2 = 1
    printf("main函数的 add函数的指针add=%p\n", add); //main函数的 add函数的指针add=00402022
    printf("main函数的 add函数的指针&add=%p\n", &add);//main函数的 add函数的指针&add=00402022
    printf("main函数的 mins函数指针mins=%p\n", mins); //main函数的 mins函数指针mins=00401F10
    printf("main函数的 mins函数指针&mins=%p\n", &mins); //main函数的 mins函数指针&mins=00401F10

    //todo add的函数指针地址 : add函数自身就是一个指针地址add=&add=00402022
    //传递实参参数: 函数指针void(*method)(int,int)=add/&add    数值num1=10  num2=10
    opreate(add,  10, 10);
    opreate(&add,  10, 10);
    // num1 + num2 = 20  opreate函数的 形参method函数指针=00402022 =add=&add

    //传递实参参数: 函数指针void(*method)(int,int)=mins/&mins    数值num1=10  num2=100
     opreate(mins,  10, 100);
     opreate(&mins,  10, 100);
  // num1 - num2 = -90   opreate函数的 形参method函数指针=00401F10= mins=&mins

    return 0;
}

// 再实现 使用
void add(int num1, int num2) {
    printf("num1 + num2 = %d\n", (num1 + num2));
}

    函数指针2: T29


    函数本身就是一个指针地址
    callBackMethod的函数指针地址 : callBackMethod函数自身就是一个指针地址callBackMethod=&callBackMethod=00402074

    
    void callBackMethod(char* fileName, int current,int total){
    printf("%s图片压缩的进度是:%d/%d\n", fileName, current, total);
    }


   //创建一个函数compress()
//定义一个函数指针地址声明   返回值(*名称)(char *,int,int)= void(*callBackP)(char *,int,int)
//函数指针名称callBackP=接收传进来的实参函数指针callBackMethod/&callBackMethod
//形参: 字符串char* fileName,数值int current,数值int total
void compress(char* fileName,int current,int total,void(*callBackP)(char *,int,int)){
     //函数指针callBackP=callBackMethod/&callBackMethod
     // callBackP(fileName,current,total)=callBackMethod("方明飞.png",5,100)
    // 形参 fileName= "方明飞.png",current=5,total=100
    callBackP(fileName,current,total);
     // 或者这样写法
    (*callBackP)(fileName,current,total);
    // 或者这样写法  // 省略*
    (callBackP)(fileName,current,total);
}

    
 给函数callBackMethod  定义一个函数指针地址void (* call1)(char*,int,int)  方式一    
  void (* call1)(char*,int,int)=callBackMethod;    
  void (* call2)(char*,int,int)=&callBackMethod;  
 
    
    
给函数callBackMethod  定义一个函数指针地址  方式二
 //先定义
// call3 函数指针地址  

/./形参 char*,int,int
 void (* call3)(char*,int,int);    
//再给指针call3赋值callBackMethod
call3 =callBackMethod;    
call3 =&callBackMethod;  
 
    
   //先定义
   void (* call5) (char *, int ,int);
    void (* call6) (char *, int ,int);
    void (* call7) (char *, int ,int);
    void (* call8) (char *, int ,int);
     //在赋值
    call6 =callBackMethod;
    call8 =&callBackMethod;    
    
   

//定义一个函数
//callBackMethod的函数指针地址 : callBackMethod函数自身就是一个指针地址callBackMethod=&callBackMethod=00402074
void callBackMethod(char* fileName, int current,int total){
    printf("%s图片压缩的进度是:%d/%d\n", fileName, current, total);
}


   //创建一个函数compress()
//定义一个函数指针地址声明   返回值(*名称)(char *,int,int)= void(*callBackP)(char *,int,int)
//函数指针名称callBackP=接收传进来的实参函数指针callBackMethod/&callBackMethod
//形参: 字符串char* fileName,数值int current,数值int total
void compress(char* fileName,int current,int total,void(*callBackP)(char *,int,int)){
     //函数指针callBackP=callBackMethod/&callBackMethod
     // callBackP(fileName,current,total)=callBackMethod("方明飞.png",5,100)
    // 形参 fileName= "方明飞.png",current=5,total=100
    callBackP(fileName,current,total);
     // 或者这样写法
    (*callBackP)(fileName,current,total);
    // 或者这样写法  // 省略*
    (callBackP)(fileName,current,total);
}


// 函数指针2: 函数本身就是一个指针地址

int main(){
      //定义一个字符串
     char* str = "方明飞";
     printf("字符串str的数值=%s\n",str); //字符串str的数值=方明飞
    printf("字符串str的指针地址=%p\n",str); // 字符串str的指针地址=00406AAC
    printf("字符串str的指针地址=%p\n",&str); //字符串str的指针地址=0061FF1C

    //todo  callBackMethod的函数指针地址 : callBackMethod函数自身就是一个指针地址callBackMethod=&callBackMethod=00402074
    printf("函数callBackMethod的指针地址callBackMethod=%p\n",callBackMethod); //函数callBackMethod的指针地址callBackMethod=00402074
    printf("函数callBackMethod的指针地址&callBackMethod=%p\n",&callBackMethod); // 函数callBackMethod的指针地址&callBackMethod=00402074


    compress("方明飞-2.png",-2,100,callBackMethod); //方明飞-2.png图片压缩的进度是:-2/100
    compress("方明飞-1.png",-1,100,&callBackMethod); //方明飞-1.png图片压缩的进度是:-1/100

    // 给函数callBackMethod  定义一个函数指针地址void (* call1)(char*,int,int)  方式一
     void (* call1)(char*,int,int)=callBackMethod;
    compress("方明飞1.png",5,100,call1); // 方明飞1.png图片压缩的进度是:5/100
    void (* call2)(char*,int,int)=&callBackMethod;
    compress("方明飞2.png",15,100,call2); //方明飞2.png图片压缩的进度是:15/100


    // 给函数callBackMethod  定义一个函数指针地址  方式二
    //先定义
    // call3 函数指针地址   形参 char*,int,int
    void (* call3)(char*,int,int);
    //再给指针call3赋值callBackMethod
    call3 =callBackMethod;
    compress("方明飞3.png",25,100,call3); //方明飞3.png图片压缩的进度是:25/100
    //先定义
    void (* call4) (char *, int ,int);
    //在赋值
    call4 =&callBackMethod;
    compress("方明飞4.png",35,100,call4); //方明飞4.png图片压缩的进度是:35/100

    void (* call5) (char *, int ,int);
    void (* call6) (char *, int ,int);
    void (* call7) (char *, int ,int);
    void (* call8) (char *, int ,int);
    call6 =callBackMethod;
    call8 =&callBackMethod;
    compress("方明飞8.png",85,100,call8); //方明飞8.png图片压缩的进度是:85/100



    return  0;

  函数指针练习

   几种函数指针的写法

   test(addMethod, 9, 9); // i+j=18
    test(&addMethod, 8, 8); //i+j=16

    void(*p1)(int,int)=addMethod;
    test(p1,7,7);  //i+j=14
    void(*p2)(int,int)=&addMethod;
    test(p2,6,6); //i+j=12

    void(*p3)(int,int);
    p3=addMethod;
    test(p3,5,5); //i+j=10

    void(*p4)(int,int);
    p4=&addMethod;
    test(p4,4,4); //i+j=8

#include 

void addMethod(int i, int j) {
    printf("i+j=%d\n", i+j);
}



// 创建函数test
// 定义一个函数指针声明void(*p)(int, int)
// 函数指针名称p=接收传进来的实参函数指针addMethod
void test(void(*p)(int,int),int num1,int num2){
    //p(num1, num2)=addMethod(9, 9)
    p(num1, num2); // 上节课 省略*
    (*p)(num1, num2); //或者这样写
    (p)(num1, num2); // 省略*   //或者这样写
    // (&p)(9, 9); 在源码没有看到这种写法
}



int main() {
    test(addMethod, 9, 9); // i+j=18
    test(&addMethod, 8, 8); //i+j=16

    void(*p1)(int,int)=addMethod;
    test(p1,7,7);  //i+j=14
    void(*p2)(int,int)=&addMethod;
    test(p2,6,6); //i+j=12

    void(*p3)(int,int);
    p3=addMethod;
    test(p3,5,5); //i+j=10

    void(*p4)(int,int);
    p4=&addMethod;
    test(p4,4,4); //i+j=8
    return 0;
}

打印随机数  

srand((unsigned) time(NULL));

// 时间单位 给他才行
    srand((unsigned) time(NULL));

    int i;
    for (int i = 0; i <10 ;i++) {
        printf("随机数%d\n", rand() % 100);
    }

 字符串的Copy 

char *strcpy(char *str1, char *str2);  

 

// 定义一个数组
char stringArr[10];
 // 定义字符串 str1
 char* str1  = "abcdefghi";

 printf("%s\n", stringArr); // 打印数组 空的
 // 就是把 字符串str1 复制到 数组stringArr里去
 strcpy(stringArr,str1);
 printf("%s\n", stringArr); // 打印数组 abcdefghi
printf("数组stringArr的长度=%d\n", sizeof stringArr / sizeof(char));// 数组arr的长度=10

C中的布尔 

非0即true, 0就是false

  if (0) {
        printf("真\n");
    } else {
        printf("假\n");
    }

    if (43665) {
        printf("真\n");    // 1  走
    } else {
        printf("假\n");    // 2
    }

    if (-545) {
        printf("真\n");    // 1
    } else {
        printf("假\n");    // 2
    }

静态开辟栈区  3T3

静态开辟的栈区的内存小,很容易溢出

执行调用某个函数  就会进栈 静态开辟栈区 定义的int arr[5];   int i; 都是栈成员
  函数执行完毕会弹栈  会释放所有的栈成员

 栈区:占用内存大小 最大值: 大概最大 2M  大于2M会栈溢出  跟平台有关系的
 堆区:占用内存大小 最大值: 大概最大占80%  40M没有任何问题,基本上不用担心 堆区很大的
                                                  大概80%: Windows系统 给我们的编译器给予的空间  的 百分之百八十

int main(){
    //兆=M
    //1兆=1M=1*1024 * 1024
    //10兆=10M=10 * 1024 * 1024
    //int类型是4个字节

    // int类型的数组arr 占用内存大小 4 * 10*1M = 40M>2M   栈会溢出
    // int arr[10 * 1024 * 1024];

    // int类型的数组arr 占用内存大小 4 *1*1M = 4M >2M 栈会溢出
    // int arr[1 * 1024 * 1024];

    // int类型的数组arr  占用内存大小 4* 0.2*1M=0.8M<2M 不会栈溢出
    int arr[(int)(0.2 * 1024 * 1024)];

return (0);
}

#include 
#include  // 小写sleep的


//todo  执行调用某个函数  就会进栈 静态开辟栈区 定义的int arr[5];   int i; 都是栈成员
void staticAction() {
    int arr[5]; //  创建栈成员 int类型数值4*5=20字节
    for (int i = 0; i <5 ; ++i) {
      arr[i]=i;
      printf("输出数组arr的元素数值%d\n",arr[i]);
      printf("输出数值arr的元素数值%d的内存地址=%p\n",*(arr+i),arr+i);
    }

}//todo 函数执行完毕会弹栈  会释放所有的栈成员


//  静态开辟栈区
int main(){
 //执行调用某个函数  就会进栈 静态开辟栈区
 staticAction();
  return (0);
}

你可能感兴趣的:(c语言)