• C语言_字符串与指针的爱恨情仇


    🔥引言_难点前的小基础

    1.字符串常量

    10是数值常量,“hello world"是字符串常量
    ①对于数值常量,编译器不会分配内存,所以也不能够取地址.
    即:printf(”%d\n",&(10));是错误的
    ②对于字符串常量,编译器会分配内存
    并且这块内存从程序执行之前创建,到程序结束之后销毁
    字符串不可修改,编译器给字符串常量分配的是只读内存.
    即printf(“%d\n”,&“abc”);是正确的

    2.定义可修改的字符串

    char s[]="hello world";//s可修改,因为是把字符串拷贝到自己空间就可读可写了
    s[0]='H';
    
    • 1
    • 2

    ①编译器看到双引号括起来的字符串,那么就会为该字符串分配只读内存,并且字符串常量一直都会存在.
    ②将字符串常量从只读内存中拷贝到字符串数组中.
    ③s字符串数组是可读可写,"hello world"字符串常量只读

    3.定义不可修改的字符串(不能修改值,只能修改指向)

    char *s ="hello world";
    printf("%s\n",s);
    
    • 1
    • 2

    字符串常量只是代表一个地址.
    从我们的角度来看,这个地方写的只是一个字符串.
    从编译器的角度,这个地方只是放了一个字符串的地址.

    结论1

    c语言的字符串都认为是char* 类型的

    补充:相同字符串,指向的是同一段内存

    char *s1 = "abc";
    char *s2 = "abc";
    
    • 1
    • 2

    图解如下:

    在这里插入图片描述

    结论2

    char*字符串只能通过修改指向的方式修改值

    🎉函数指针

    char * my_bussinese(){
        char s[]="hello world";
        return s;
    }
    char * my_logic(){
        char * s ="hello world";
        return s;
    }
    void main(){
        char *s1=my_bussinese();
        char *s2=my_logic();
        printf("s1=%s\n",s1);  ====>输出 s1=烫烫烫烫
        printf("s2=%s\n",s2);  ====>输出 s2=hello world
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    s1错误输出的原因:内存释放后,无论里面存的值是否正确都必须停止使用

    my_businese图解如下:

    在这里插入图片描述

    my_logic图解如下:
    在这里插入图片描述

    ✨关于多级指针

    一级指针存放的是变量的地址.
    二级指针存放的是一级指针的地址.(实际上,在工作学习中,最多用到二级指针)
    三级指针存放的是二级指针的地址.

    eg:

    int a=10;
    int *p1=&a;
    int* *p2=&p1;
    int** *p3=&p2;
    
    • 1
    • 2
    • 3
    • 4

    图解如下:

    在这里插入图片描述

    🎖️修改一级指针的指向

    方法一:直接修改地址

    int a=10;
    int b=20;
    int *pa = &a;
    pa = &b;//此时,*pa的值已经修改为20
    
    • 1
    • 2
    • 3
    • 4

    方法二:二级指针间接修改

    int a=10;
    int b=20;
    int *pa = &a;
    int **ppa=&pa;
    *ppa =&b;//此时,*pa的值已经修改为20
    //============> *ppa是对ppa进行了一次解引,找出来ppa里面放的地址,就是pa的地址,  即*ppa相当于pa 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    🔓二级指针函数

    void pointer_to_string(char **s){
        *s="hello world";//s是二级指针,*s解引了一次,表示拿到s里面存放的地址
        //**s表示解引了二次,找到p里面的地址(null的地址还为null)
    }
    void test02(){
        char *p=nullptr;
        pointer_to_string(&p);//一级指针的地址是二级指针,二级指针存放的是一级指针的地址
        printf("p=%s\n",p);
    }
    void main(){
        test02();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    图解如下:

    在这里插入图片描述

    🎆指针数组

    void print_string(char **ns,int len){
        for(int i=0;i<len;i++){
            printf("%s\n",ns[i]);//操作数组用下标
        }
    }
    void test03(){
        char *names[]={"Trump","Obama","Smith"};
        print_string(names,3);
    }
    void main(){
        test03();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    指针例题练习

    void main(){
        char *p,*q;
        p=(char*)malloc (sizeof(char)*20);
        q=p;
        scanf("%s%s",p,q);//假设输入abc def
        printf("%s%s\n",p,q);//输出的是defdef
    }
    //在最开始的引言部分中,我们说同一个字符串常量,指针指向的同一块位置,
    //这里,p和q都指向的是同一段空串空间,所以后输入的def将abc覆盖了.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    🧭用指针实现字符串拷贝

    void copy_string(char *dst,char *src){
        if(nullptr==dst){printf("dst指针为空.\n");return;}
        if(nullptr==src){printf("src指针为空.\n");return;}
        char *s =src;//新指针与src共同指向"hello world"
        while(*s != '\0'){
            *dst = *s;//因为数组指向的是数组元素的首地址,
            //解引一次后指向的是第一个元素,故只能一个元素一个元素的拷贝
            ++s;
            ++dst;
        }
        *dst = *s;//将s最后的字符\0拷贝到目标空间
    }
    void test(){
        char *src="hello world";//源字符串
        char dst[128]={0};//定义目标字符串
        copy_string(dst,src);//拷贝字符串
        printf("dst = %s \n",dst);//输出拷贝完成的字符串
    }
    void main(){
        test();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    SpringCloud Netflix-Hystix使用
    Java怎么实现word转PDF?
    【21天学习挑战赛】算法——选择排序
    [晕事]今天做了件晕事24;GCC -W
    linux网络协议栈源码分析 - 传输层(TCP连接的终止)
    深度学习——模型选择、欠拟合和过拟合
    栈的应用:括号匹配,递归
    从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(九)文件服务篇(1):minio 单机与集群搭建
    MongoDB 语法大全
    C语言执行过程
  • 原文地址:https://blog.csdn.net/weixin_52668597/article/details/125419326