美文网首页
C语言提高

C语言提高

作者: hgzzz | 来源:发表于2020-10-31 12:50 被阅读0次

    数据类型与变量

    1. 数据类型
      • 类型相同的数据具有相同的表示形式、存储格式和操作,程序中所以数据必须属于某种数据类型。
      • 为编译器提供分配内存大小的依据,数据类型本身没有内存空间。
      • 使用typedef给类型起别名方便使用。
      • void:无类型,用来定义指针 void *p,函数返回值,函数参数。
    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      int arr[] = {1, 2, 3};
      printf("%d\n", sizeof(arr)); // 12
    
      // arr = 6422308 arr + 1 = 6422312
      // arr 表示数据手元素地址 + 1 加的是一个元素的长度4
      printf("arr = %d arr + 1 = %d\n", arr, arr + 1);
    
      // &arr = 6422308 &arr + 1 = 6422320
      // &arr 表示的是整个数组的首地址 + 1,加整个数组的长度12
      printf("&arr = %d &arr + 1 = %d\n", &arr, &arr + 1); 
      return 0;
    }
    
    1. 变量:变量的使用要抓住生命周期和作用域两点。
      • 全局变量(包括静态(文件内使用),普通(可跨文件使用))。
      • 局部变量(函数中的变量,形参,函数内使用)。
      • 生命周期伴随程序结束:静态变量(包括全局和局部,存放在data区),全局变量。
      • 函数执行完成销毁:局部变量,形参。
      • 有些局部变量指向堆区地址,在函数执行结束时,形参销毁但是堆区地址不会自动回收,只有free()函数回收。

    内存分区(stack、heap、data、bss、text)

    1. stack:栈区,存放函数执行过程中的局部变量和形参,函数调用完毕释放。
      • 栈区地址由高向低使用,栈区有一定的大小限制,超过会造成堆栈溢出问题。

    指针、函数指针

    1. 数组在作为形参时会退化为指针,在接收数组参数时,形参可以直接写指针形式。
    #include <stdio.h>
    
    int func(int arr[]){
      return sizeof(arr);
    }
    
    int func1(int arr[3]){
      return sizeof(arr);
    }
    
    int func2(int *arr){
      return sizeof(arr);
    }
    
    int main(int argc, char const *argv[])
    {
      int arr[3] = {1, 2, 3};
      printf("数组的长度为:%d\n", sizeof(arr));  // 12(int * 3)
    
      printf("func 数组形参的长度为:%d\n", func(arr)); // 4 32位系统中一个指针的长度
    
      printf("func1 数组形参的长度为:%d\n", func1(arr)); // 4
    
      printf("func2 数组形参的长度为:%d\n", func2(arr)); // 4
      return 0;
    }
    
    1. 指针是大小固定(与编译器决定)的数据类型。
      • 指针变量存储一个地址,它通过这个地址访问对应的地址块。
    2. 二级指针做形参,接收一个一级指针的地址。
      • 在使用指针类型形参时,要先做判断,防止段错误。
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    void func(char **p, int *len){
      if(p == NULL || len == NULL){
        return;
      }
      char *temp = (char *)malloc(100);
      strcpy(temp, "hgzzz");
      *p = temp;
      *len = strlen(temp);
    }
    
    int main(int argc, char const *argv[])
    {
      char *p = NULL;
      int len = 0;
      func(&p, &len);
      printf("%s  %d\n", p, len); // hgzzz  5
      return 0;
    }
    

    字符串处理

    1. 函数接收字符串数组。
    #include <stdio.h>
    #include <string.h>
    
    void print_arr(char **str_arr ,int len){
      if(str_arr == NULL){
        return;
      }
      int i;
      for(i = 0; i < len; i++){
        printf("%s ", str_arr[i]);
      }
    }
    
    void sort_arr(char **str_arr ,int len){
      if(str_arr == NULL) {
        return;
      }
      int i,j;
      char *temp;
      for(i = 0; i < len - 1; i++){ // 快速排序
        for(j = i + 1; j < len; j++){
          if(strcmp(str_arr[i], str_arr[j]) > 0){
            temp = str_arr[i];
            str_arr[i] = str_arr[j];
            str_arr[j] = temp;
          }
        }
      }
    }
    
    
    int main(int argc, char const *argv[])
    {
      char *str_arr[] = { "aaa", "vvv", "ccc", "bbb" };
      int len = sizeof(str_arr) / sizeof(str_arr[0]);
    
      printf("排序前\n"); // aaa vvv ccc bbb 
      print_arr(str_arr, len);
    
      sort_arr(str_arr, len);
    
      printf("\n排序后\n"); // aaa bbb ccc vvv 
      print_arr(str_arr, len);
      printf("\n");
      return 0;
    }
    

    sizeof()

    1. sizeof()是运算符,不是函数,sizeof()部分在编译之前就已经确定结果。
    #include  <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      int a;
      printf("int_len = %d\n", sizeof(a)); // int_len = 4
    
      char *p;
      printf("pointer_len = %d\n",sizeof(p)); // pointer_len = 4
    
      return 0;
    }
    
    1. sizeof()可以求得void类型指针的长度,但是无法求得void类型变量的长度。因为这样的变量无法分配内存大小,所以你也定义不了。但是指针是存储的一个地址,地址是根据编译器的位数决定的,所以指针的大小是确定的,比如32位编译器分配的指针就是4个字节的大小。
    #include  <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      /* 
      void a; // error: variable or field 'a' declared void
      printf("void_variable_len = %d\n", sizeof(a));
      */
      void *p;
      printf("void_pointer_len = %d\n", sizeof(p)); // void_pointer_len = 4
    }
    
    1. sizeof()求静态分配内存的数组的大小
    #include <stdio.h>
    
    int func(int arr[2]){
      return sizeof(arr);
    }
    
    int main(int argc, char const *argv[])
    {
      int int_arr[2] = {0};
      printf("int_arr_len = %d\n", sizeof(int_arr)); // int_arr_len = 8
    
      char char_arr[3] = {'a', 'b', 'c'};
      printf("char_arr_len = %d\n", sizeof(char_arr)); // char_arr_len = 3
    
      // 字符串数组,默认结尾加上结束符'\0'
      char str_arr[] = "hgz";
      printf("str_arr_len = %d\n", sizeof(str_arr)); // str_arr_len = 4
    
      // 数组作为函数参数,形参退化成指针,提高运行效率
      printf("arr_arg_len = %d\n", func(int_arr)); // arr_arg_len = 4
      return 0;
    }
    

    数组

    1. 指针数组,数组里面存储指针类型的变量。
    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      int i = 0;
      // 指针数组,数组里面存储指针类型
      char *str_arr[] = {"aaa", "bbb", "ccc"};
      for(i = 0; i < sizeof(str_arr)/sizeof(str_arr[0]); i++){
        printf("%s\n", str_arr[i]);
        printf("%d\n", sizeof(str_arr[i])); // 4
      }
    
      return 0;
    }
    
    1. 数组指针,指向整个数组的指针,而不是首元素。
    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      int arr[10] = {0};
    
      typedef int int_arr_10[10];
      int_arr_10 *p = NULL;
      p = &arr;
      // p = 6422276 p + 1 = 6422316 步长是一个数组的大小
      printf("p = %d p + 1 = %d\n", p, p+1);
    
      // 定义数组指针类型
      int(*q)[10];
      q = &arr;
      printf("%d\n", q);
      return 0;
    }
    
    1. 二维数组
    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
      int arr[][2] = {{1, 2}, {3, 4}, {5, 6}};
      // 差8个字节,步长为一行
      printf("arr = %d arr+1 = %d\n", arr, arr+1); 
      // 差24字节,步长为整个二维数组的长度
      printf("&arr = %d &arr+1 = %d\n", &arr, &arr+1); 
      return 0;
    }
    

    相关文章

      网友评论

          本文标题:C语言提高

          本文链接:https://www.haomeiwen.com/subject/pgqqgctx.html