const

  • const 是一个关键字,是用来修饰我们的变量的,也就是在声明变量的同时,可以使用 const 关键字来修饰
  • 一般来说,被 const 修饰的变量具有一定程度的不可变性
  • const 修饰基本数据类型(int ,double ,float , char)
    const int num = 10;
    num = 20;
// 报错:Cannot assign to variable 'num' with const-qualified type 'const int',不能为 const 修饰的变量进行赋值
  • const 修饰数组,数组的元素的值不能修改
    const int nums[5] = {1,2,3,4,5};
    nums[0] = 10;
// 报错:Cannot assign to variable 'nums' with const-qualified type 'const int [5]'

    const int nums[5] = {1,2,3,4,5}; // 完全初始化不能修改
    // nums[0] = 10;
    const int nums1[5] = {1,2}; // 部分初始化也不能修改
    // nums1[3] = 30;
    const int nums2[3]; // 未初始化的也不可以
    // nums2[0] = 10;
  • const 修饰指针(const int* p1 = &num int const * p1 = &num)
  • 无法通过指针去修改指针指向的变量的值,但是如果直接操作变量的话是可以的
  • 但是指针变量的值是可以改的,可以把另外一个变量的地址赋值给这个指针
    int num = 10;
    const int* pnum = # // 无法通过指针去修改指针变量指向的变量的值
    *pnum = 100; // 只读变量不可修改
    printf("num = %i\n",num);
  • const 修饰指针 2(int * const p1 = &num)
  • 此时代表不能修改 p1 的值,但是可以去修改 p1 指向变量的值
    // 修饰指针:   const int * pnum / int const *pnum    -->修饰的*pnum
//    int num = 10;
//    const int* pnum = # // 无法通过指针去修改指针变量指向的变量的值
//    *pnum = 100; // 只读变量不可修改
//    printf("num = %i\n",num);
    
    // 修饰指针:    int * const p1 = #    --> 修饰的 p1
    int num = 10;
    int * const p1 = #
    *p1 = 100; // 修改值是可以的
    printf("修改值后的 num 值:%i\n",num);
    
    int age = 20;
    // p1 = &age; // 此时不能修改p1 的值,也就是只能指向这个地址,不能指向别的地址,还能修改变量的值
    
    //修饰指针:int const * const pnum = # -->修饰的* pnum 和 pnum
    int num2 = 30;
    int const * const pnum = #
    // *pnum = 300; // 不可修改
    int num3 = 40;
    // pnum = &num3; // 不可修改
  • const 使用场景
    • const 修饰的特点
    • 被 const 修饰的变量,是制度变量,只能去值,而不能改值,所以 const 变量的值自始至终是不会发生的
    • 当某些数据是固定,在整个程序运行期间是不会发生变化的,并且你也不允许别人去修改,那么这个时候我们就可以使用 const
    • 当函数的参数是一个指针的时候,这个时候,函数的内部有可能会修改实参变量的值,这个时候,函数想传递给调用者一个信息:不能修改实参变量的值,这个时候就可以给参数加一个 const
    • 所以以后再调用这个函数的时候,这个参数被 const 修饰那么绝对修改不了我们的值
void fornum(int arr[],int len);
void conForNum(const int arr[],int len);


int main(){
         // const 应用场景
    // 我要写一个函数,但是不能修改我数组的值
    int arr[] = {1,23,45,6,7,8,9,5,3,234,423,4};
    int len = sizeof(arr) / sizeof(arr[0]);
    fornum(arr,len); // 哇此时发现被其他函数调用了但是,我的数组值可能被修改了
    for (int i = 0 ; i < len; i++) {
        printf("main 函数中的 arr 数组的值arr[i] = %i\n:",arr[i]); // 因为传递的指针,所以函数中修改了我这里也修改了,那么怎么能保证我的数据不能被修改,我只给你用但是你不能修改
    };
    
    int arr2[] = {1,2,4,5,6,78,9};
    int len2 = sizeof(arr2) / sizeof(arr2[0]);
    conForNum(arr2, len2);//
    
    return 0;
}

void fornum(int arr[],int len){
    for (int i = 0 ; i < len; i++) {
        arr[i] = arr[i]+10;
        printf("arr[i] = %i\n",arr[i]);
    };
    
}

void conForNum(const int arr[],int len){
    for (int i = 0 ; i < len; i++) {
        // arr[i] = arr[i]+10; // 报错:只读变量不可赋值
        printf("arr[i] = %i\n",arr[i]);
    };
    
}

static和 extern

  • 这是我们 C语言中的两个关键字,用来修饰变量和函数

    • static 和 extern 修饰局部变量的效果
    • static 和 extern 修饰全局变量的效果
    • static 和 extern 修饰函数的效果
  • static 和 extern 修饰局部变量的效果

    • 如果我们的局部变量被 static 修饰,这个变量就叫做静态变量

    • 静态变量不在存储在栈区域而是存储在常量区

    • 当函数完毕之后,这个静态变量不会被回收,下次再执行这个函数的时候拿来用就可以了.

    • 第一次执行这个函数的时候就会将这个静态变量声明在常量区,函数执行完毕之后这个静态变量不会被回收的,后面再去执行这个函数的时候,声明静态变量的这句话就不会再执行了,而是直接略过,直接使用这个静态变量的值

    • static 修饰的静态变量,函数结束不会被回收,仍然存在,函数无论执行多少次这个静态变量只有 1 份

    • extern 不能修饰局部变量

int test1();
int main(){
    printf("num = %i\n",test1());
    printf("num = %i\n",test1());
    printf("num = %i\n",test1());
    printf("num = %i\n",test1());
    return 0;
}

// staticx修饰局部变量
int test1(){
    static int num = 10;
    return num++;
}
  • static 和 extern 修饰全局变量

    • 1,写一个函数,最完整的步骤应该分两步

      • 1,先写函数的声明
      • 2,再写函数的实现
    • 2,我们写 1 个全局变量最完整的步骤也应该分为两步

      • 1,先写全局变量的声明,只定义全局变量而不赋值,这个就叫做全局变量的声明,int num;

      • 2,再写全局变量的定义,定义全局变量并初始化,也叫做全局变量的实现

      • Int num = 10;

      • 这个时候,全局变量的声明可以放在使用这个全局变量的前面,全局变量的定义可以放在使用全局变量的后面,这个时候仍然可以正常取值

    • 3,全局变量可以只有声明,没有定义,那么编译器就会自动的帮我们去实现这个全局变量,自动实现的时候,会将这个全局变量自动初始化为 0

    • 4,全局变量也可以只有定义,没有声明,但是这个时候这个全局变量的定义必须要在使用全局变量的函数前面

    • 5,当我们分模块开发的时候,如果要在模块中声明全局变量

      • 1,全局变量的声明要写在.h 文件中
      • 2,全局变量的实现要写.c文件中
      • 3,如果将这个全局变量定义在模块中,这个全局变量必须要是用 static 或者 extern 来修饰
      • 4,如果定义在模块中的全局变量使用 extern 来修饰,这个模块中的全局变量就可以跨模块来访问
      • 5,如果定义在模块中的全局变量使用 static 来修饰,这个模块中的全局变量就只能在当前模块中访问,虽然跨模块导入不包吃,但是没有取到真正的值
    // main.c 模块
    # include "test.h"
    int main(){
        // static 修饰全局变量
        printf("static修饰全局变量:%i\n",num1);
        // extern 修饰全局变量
        printf("extern修饰全局变量:%i\n",num);
    }
    
    // test.h 模块
    
    #ifndef test_h
    #define test_h
    
    #include <stdio.h>
    extern int num; // 全局变量的声明
    
    static int num1;
    #endif /* test_h */
    
    
    // test.c 模块
    
    #include "test.h"
    int num = 10; // 全局变量的实现,extern 修饰时在实现的时候不用写 extern
    static int num1 = 20; // static 修饰全局变量
    
    
  • static 和 extern 修饰函数

    • 如果函数被 extern 修饰这个函数,那么这个函数就可以跨模块调用
    • 如果函数被 static 修饰,那么这个函数只能在当前模块中调用,无法调用
    • 如果函数没有写 static 或者 extern,那么这个函数默认就是 extern
posted on 2020-06-11 23:10  python我学的很菜  阅读(414)  评论(0编辑  收藏  举报