• C指针笔记


    基础要好,房子才能盖的牢固,才能盖的高。先把基础补一补,再多刷点算法题看看。
    1.c语言指针必须要先赋值才能够使用,不赋值就使用指针的指向是未知的。
    2.指针是存放地址的变量。
    3.数组名是一个地址,可以直接赋值给指针。

    int num[4] = {1,2,3,4};
    int *pNum;
    pNum = num;	//将数组地址值,赋值给指针。
    
    pNum++; //指向数组的指针自加,自加一个元素长度的地址,指向下一个元素。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.指针与常数加减,都是加减对应的元素。(就是指针+1:指向下一个数组元素,其余加减法也是以元素为最小的符号)

    int *pNum2;
    pNum2 = pNum+3; //pNum地址值指向数组最后一个元素4。
    
    int count = pNum2-pNum; //结果为3,即num[0]和num[3]之间索引相减。3-0=3;(指针的算术运算只在同一数组内有意义,两个不同数组的指针运算结果不确定,可能会出错)
    
    • 1
    • 2
    • 3
    • 4

    5.数组在声明之后只能一个一个的赋值,不能直接数组名放在等号左边赋值,因为等号左边必须是变量。

    int array[3];
    array = {1,2,3}; //这样赋值是错误的。
    
    • 1
    • 2

    6.指针的算术加减运算是以指针的类型为基本单元,char指针+1就是加一个字节(char的长度1个字节)。int指针+1就是加四个字节(int的长度4个字节)。如下:

    int main(){
        char charArr[7] 
        int intArr[7] = 
        
        char *pCharArr;
        char *pCharArr1;
        char *pCharArr2;
        char *pCharArr3;
    
        int *pIntArr;
        int *pIntArr1;
        int *pIntArr2;
        int *pIntArr3;
    
        pCharArr = charA
        pIntArr = intArr
    
        pCharArr1 = char
        pCharArr2 = char
    
        pIntArr1 = intAr
        pIntArr2 = intAr
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述
    7.c指针数组声明(就是数组元素都是指针)

    int *num[3]; //声明一个名字是num的指针数组,数组中有三个int类型的指针元素,(同一指针数组中只能存放统一类型数据,数组中也是一样)
    
    • 1

    8.指针声明但不初始化时必须要加上数组的长度,指针声明并直接初始化时可以不用加数组长度。

    char name[10]; //声明一个长度10个char元素的数组name,声明数组但不初始化必须加数组长度。
    char address[] = {"abcdef"}; //声明一个数组并直接初始化,可以不加数组长度。
    
    
    • 1
    • 2
    • 3

    9.函数形参(指针除外)作用域只在函数内有效,函数间传值用函数返回值传递,或使用指针。

    #include 
    typedef unsigned char uint8_t;
    extern void swapdata(uint8_t dat_x,uint8_t dat_y);
    
    int main(){
        uint8_t x,y;
    
        printf("请输入x,y:\n");
        scanf("%d,%d",&x,&y);
        printf("交换前x=%d,y=%d\n",x,y);
        swapdata(x,y);
        printf("交换后x=%d,y=%d\n",x,y);
    }
    
    //函数的形参只在函数内有效,是函数创建的临时变量,离开函数就失效了。无法改变实参的值。
    void swapdata(uint8_t dat_x,uint8_t dat_y){
        uint8_t temp;
        temp = dat_x;
        dat_x = dat_y;
        dat_y = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入代码片

    利用指针传递值,指针是指向数据的地址,指针指向的对应地址中保存着指针(*运算后取值后)的数据。
    有点乱不知道怎么解释好了。

    #include 
    typedef unsigned char uint8_t;
    extern void swapdata(uint8_t *dat_x,uint8_t *dat_y);
    
    int main(){
        uint8_t x,y;
        uint8_t *p_x,*p_y; //指针作为中间参数,好像不占有空间,让指针指向x和y。一个数据可以有一个指针,我还以为是重新又创建了一个中间变量,其实不是。一个数据可以创建一个指针指向他。
    
        printf("请输入x,y:\n");
        scanf("%d,%d",&x,&y);
        p_x = &x; //将指针变量指向x和y。
        p_y = &y;
    
        printf("交换前x=%d,y=%d\n",x,y);
        swapdata(p_x,p_y);
        printf("交换后x=%d,y=%d\n",x,y);
    }
    
    //指针类型的参数就是地址,所以使用函数时,传递的是地址。
    void swapdata(uint8_t *dat_x,uint8_t *dat_y){
        uint8_t temp;
        temp = *dat_x;
        *dat_x = *dat_y; //将指针指向的数据,赋值给另外一个指针指向的数据。
        *dat_y = temp; //同理,给指针参数赋值。
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    10.主函数需要将实参作为指针传递给被调用函数,被调用函数才可能改变实际参数。

    void test(int *arg1,char *arg2); //像这样的函数,参数是指针。
    
    • 1

    11.数组名是地址,可以将其直接赋值给指针。如下

    int arr[] = {1,2,3}; //数组名arr是个地址
    int *p_arr; //*后面指针名也是个地址,(*地址)声明一个类型的指针。
    p_arr = arr; //完成指针初始化,将指针指向数组首地址。
    
    • 1
    • 2
    • 3

    12.结构体中有数组的话,声明结构体时不用再另外加括号。按照顺序声明每个数据即可。
    (结构体数组,一个数组里面都是结构体,哈哈哈,结构体里面还可以再有数组,无限套娃。)

    typedef struct 
    {
        uint8_t data;
        uint8_t name;
        uint8_t someData[DATA_MAX]; //这是个结构体中的数组。声明时直接按照元素索引顺序排列即可,无需另外加括号,结构体就是一段连续的存储单元,存储着一组数据。
        uint8_t age;
    }MY_OWN_STRUCT;
    
    //声明结构体数组
    MY_OWN_STRUCT my_struct[STRUCT_MAX] = {
        {0x11,0x12,0x13,0x13,0x13,18},
        {0x22,0x13,0x14,0x14,0x14,25},
        {0x33,0x14,0x15,0x15,0x15,50}
    };
    
    uint8_t test = mystruct[1].data; //调用结构体中数据
    uint8_t arr = mystruct[2].someData[1]; //调用结构体中的数组元素
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    13.普通变量作为函数参数传递时,把实参的值传递给形参,也就是说形参值是实参值的拷贝,形参和实参虽然是同样的值,但存储在不同的内存空间中。在被调用函数中,是对形参的操作,而对实参没有进行任何操作。普通变量作为函数参数时,实参值不会进行变化。而指针变量作为函数参数时,通过指针变量的值传递,是让形参指向实参变量指向的变量,通过指针变量的值传递后,形参变量和实参变量指向同一个变量。所以,在被调用函数中,对形参的操作,就是对其指向变量的操作。

  • 相关阅读:
    【必知必会的MySQL知识】②使用MySQL
    阿里内部热捧“Spring全线笔记”,不止是全家桶,太完整了
    155. RESTframe的请求和响应
    中断系统结构及中断控制详解
    Unity内实现无卡顿取图像推流/截屏等功能
    卷积网络的发展历史-AlexNet
    Spring MVC ⾼级技术:监听器、过滤器和拦截器
    基于Springboot实现毕业生信息招聘平台管理系统演示【项目源码+论文说明】分享
    redis开启ipv6访问
    Redis的高可用集群 完
  • 原文地址:https://blog.csdn.net/qq_38489451/article/details/126086161