zoukankan      html  css  js  c++  java
  • C语言 指针

    一、C语言 指针基础

    1、内存地址

    1、内存含义

    • 存储器:计算机的组成中,用来存储程序和数据,辅助CPU进行运算处理的重要部分。
    • 内存:内部存贮器,暂存程序/数据——掉电丢失 SRAM、DRAM、DDR、DDR2、DDR3。
    • 外存:外部存储器,长时间保存程序/数据—掉电不丢ROM、ERRROM、FLASH(NAND、NOR)、硬盘、光盘。

    2、内存是沟通CPU与硬盘的桥梁

    • 暂存放CPU中的运算数据
    • 暂存与硬盘等外部存储器交换的数据

    3、物理存储器和存储地址空间

    • 有关内存的两个概念:物理存储器和存储地址空间

    4、物理存储器:实际存在的具体存储器芯片

    • 主板上装插的内存条
    • 显示卡上的显示RAM芯片
    • 各种适配卡上的RAM芯片和ROM芯片

    5、存储地址空间:对存储器编码的范围。我们在软件上常说的内存是指这一层含义

    • 编码:对每个物理存储单元(一个字节)分配一个号码
    • 寻址:可以根据分配的号码找到相应的存储单元,完成数据的读写

    6、内存地址

    • 将内存抽象成一个很大的一维字符数组。
    • 编码就是对内存的每一个字节分配一个32位或64位的编号(与32位或者64位处理器相关)。
    • 这个内存编号我们称之为内存地址。

    7、内存中的每一个数据都会分配相应的地址

    • char:占一个字节分配一个地址
    • int: 占四个字节分配四个地址
    • float、struct、函数、数组等

    2、指针变量

    一、概述

    • 内存区的每一个字节都有一个编号,这就是“地址”。
    • 如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定它的内存地址(编号)
    • 指针的实质就是内存“地址”。指针就是地址,地址就是指针。
    • 指针是内存单元的编号,指针变量是存放地址的变量。
    • 通常我们叙述时会把指针变量简称为指针,实际他们含义并不一样。

    二、数据存储格式

    注:windos电脑在做数据存储时采用小端对齐。

    注:Linux 电脑在做数据存储时采用大端对齐。

    三、定义说明

    • 指针也是一种数据类型,指针变量也是一种变量
    • 指针变量指向谁,就把谁的地址赋值给指针变量
    • “*”操作符操作的是指针变量指向的内存空间

    注意:&可以取得一个变量在内存中的地址。但是,不能取寄存器变量,因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的。
    注意:&是取地址符号是升维度的、*是取值符号是将维度的。
    注意:在定义指针类型一定要和变量的类型对应上。

    四、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 定义指针变量存储变量地址
        int a = 10;
        // 指针类型:数据类型*
        int* p;
        p = &a;
        // 通过指针间接改变变量的值
        *p = 100;
        printf("%p
    ", &a);
        printf("%p
    ", p);
        printf("%d
    ", a);
        printf("%d
    ", *p);
        return 0;
    }
    指针变量 使用案例:int类型指针修改值
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        char ch = 'a';
        char* p = &ch;
    
        // 所有指针类型存储都内存地址,内存地址都是一个无符号十六进制整形数
        // 32位操作系统所有指针类型:内存占用4字节
        // 64位操作系统所有指针类型:内存占用8字节
        printf("%d
    ", sizeof(int*));
        printf("%d
    ", sizeof(char*));
    
        return 0;
    }
    指针变量 使用案例:指针在内存中占用字节大小
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
        
        // P 和 arr 不同点
        // 指向数组指针
        int* p = arr;
    
        // 相同点
        //p[i]
        //*(p+i)
    
        // 不同点
        // p 是变量、arr是常量
        // p 是一个指针4个字节大小
        // arr 是一个数组是40个字节大小
        printf("指针类型大小%d
    ", sizeof(p));
        printf("数组大小%d
    ", sizeof(arr));
        
        // 数组作为函数参数会化为指针、丢失数组的精度
        // 通过 int* 将指针变为值
        // void BubbleSort(int arr[])
        // void BubbleSort(int* arr[],int len)
    
        return 0;
    }
    指针变量 使用案例:指针与变量不同点

    3、野指针

      指针变量也是变量,是变量就可以任意赋值,不要越界即可(32位为4字节,64位为8字节),但是,任意数值赋值给指针变量没有意义,因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域)。所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用)

           int a = 100;
           int *p;
           p = a; //把a的值赋值给指针变量p,p为野指针, ok,不会有问题,但没有意义
     
           p = 0x12345678; //给指针变量p赋值,p为野指针, ok,不会有问题,但没有意义
     
           *p = 1000;  //操作野指针指向未知区域,内存出问题,err

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 野指针 -> 指针变量指向一个未知的空间
        // 不建议将一个变量的值直接赋值给指针
        // 程序中允许存在野指针
        int* p = 100;
        // 操作系统将0-255作为系统占用不允许访问操作
        // 操作野指针对应的内存空间可能报错
        printf("%d
    ", *p);
    
        return 0;
    }
    野指针 使用案例

    4、空指针

    C语言中,可以把NULL赋值给此指针,这样就标志此指针为空指针,没有任何指针。

    // 空指针
    int *p = NULL;
     
    // NULL是一个值为0的宏常量:
    #define NULL    ((void *)0)

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 空指针是指内存地址编号为0的空间
        int* p = NULL;
        // 操作空指针对应的空间一定会报错
        *p = 100;
        printf("%d
    ", *p);
        // 空指针可以用作条件判断
        if (p == NULL)
        {
            
        }
        return 0;
    }
    空指针 使用案例

    5、万能指针

    void *指针可以指向任意变量的内存空间。

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        int a = 10;
        // 万能指针可以接受任意类型变量的内存地址
        void * p = &a;
        // 再通过万能指针修改变量的值时,需要找到变量对应的指针类型
        *(int*)p = 100;
        printf("%d
    ", a);
        printf("%d
    ", *(int*)p);
        // printf("万能指针在内存占得字节大小:%d
    ", sizeof(void*));
        return 0;
    }
    万能指针 使用案例

    6、const 修饰指针

    const 修饰可以约束指针类型或值得修改,但使用+1级别指针也可以让const无效。

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 1、
        // 常量:不允许修改
        // 存储空间:栈区(可指针间接修改)
        const int a = 10;
    
        // 指针间接修改常量值
        int* p = &a;
        *p = 100;
        printf("%d
    ", a);
    
        // 2、
        // const 修饰指针类型(内存空间)
        int a = 10;
        int b = 20;
        const int* p = &a;
    
        // 可以修改指针变量的值
        // 不可以修改指针内存空间的值:*p = 100;
        p = &b;
        printf("%d
    ", *p);
    
        // 3、
        // const 修饰指针变量
        int c = 10;
        int d = 20;
        int* const p = &c;
    
        // 可以修改指针类型(内存空间)的值
        // 不可以修改指针内存空间的值:p = &d;
        *p = 100;
        printf("%d
    ", *p);
    
    
        // 4、
        // const 修饰指针变量、类型(内存空间)
        // 只读指针
        int e = 10;
        int f = 20;
        // 不可以修改指针内存空间的值:*p = 100;
        // 不可以修改指针内存空间的值:p = &f;
        const int* const p = &e;
    
        // 二级指针操作
        // 可通过二级指针修改一级指针内存空间的值:
        int** pp = &p;
        // *pp是一级指针的值(内存空间)
        *pp = &b;
        // **pp是变量的值、**代表将了一个维度
        **pp = 100;
        printf("%d
    ", *p);
    
    
        return 0;
    }
    const修饰指针 使用案例
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main(void)
    {
           //const修饰一个变量为只读
           const int a = 10;
           //a = 100; //err
     
           //指针变量, 指针指向的内存, 2个不同概念
           char buf[] = "aklgjdlsgjlkds";
     
           //从左往右看,跳过类型,看修饰哪个字符
           //如果是*, 说明指针指向的内存不能改变
           //如果是指针变量,说明指针的指向不能改变,指针的值不能修改
           const char *p = buf;
           // 等价于上面 char const *p1 = buf;
           //p[1] = '2'; //err
           p = "agdlsjaglkdsajgl"; //ok
     
           char * const p2 = buf;
           p2[1] = '3';
           //p2 = "salkjgldsjaglk"; //err
     
           //p3为只读,指向不能变,指向的内存也不能变
           const char * const p3 = buf;
     
           return 0;
    }
    const修饰指针 使用案例:2
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 定义int类型
        const int a = 10;
        // 直接不可以修改
        // a = 100; //err
        // 通过一级指针修改
        int* p = &a;
        *p = 100;
    
        // 定义char类型
        char ch1[] = "hello";
        char ch2[] = "hello";
        // 指向常量指针:可以修改指针变量的值、不可以修改指针变量指向内存空间的值
        const char* p = ch1;
        // *p = 'm';//err
        // p = ch2;//ok
        // p[2] = 'm';//err
    
        // 定义char类型
        char ch3[] = "hello";
        char ch4[] = "hello";
        // 常量指针:可以修改指针变量指向内存空间的值、不可以修改指针变量的值
        char* const p = ch3;
        // p = ch4;//err
        // p[2] = 'm';//ok
        // *(p + 2) = 'm';//ok
    
        // 定义char类型
        char ch5[] = "hello";
        char ch6[] = "hello";
        // 不可修改变量与内存
        const char* const p = ch5;
        // p = ch6;//err
        // p[2] = 'm';//err
        // *p = 'm';//err
        // 二级指针
        char** p1 = &p;
        // *p1 = ch2;//ok
        // *(*p1+1) = 'm';//ok
    
        return 0;
    }
    const修饰指针 使用案例:3

    二、C语言 指针使用

    1、指针类型运算

    • 指针计算不是简单的整数相加
    • 如果是一个int *,+1的结果是增加一个int的大小
    • 如果是一个char *,+1的结果是增加一个char大小

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
        
        // 数组名是一个常量 不允许赋值
        // 数组名是数组首元素地址
        // aar = 100; //err
        // 创建指针变量
        int* p;
        p = arr;
        printf("%p
    ", p);
    
        // 打印数组第一个值
        printf("%d
    ", *p);
        printf("%p
    ", arr);
    
        // *取值(arr内存地址+1) 、相当于arr[1]
        printf("%d
    ", *(arr + 1));
    
        // 指针类型变量+1:等同于内存地址+sizeof(类型)
        printf("%d
    ", *(p + 1));
    
        // 指针p++:等同于内存地址+sizeof(类型)
        *p = 123;
        p++;
        printf("%p
    ", arr);
        printf("%p
    ", p);
    
        for (int i = 0; i < 10; i++)
        {
            // 打印数组值
            printf("%d
    ", p[i]);
            printf("%d
    ", *(p + i));
    
            // 打印数组值
            printf("%d
    ", *p++);
        }
    
        // 两个指针相减 得到的结果是两个指针的偏移量(步长)
        // 所有的指针类型 相减结果都是int类型
        // 3c 40 +1 相当于 sizeof(int) 40/sizeof(int)
        int step = p - arr;
        printf("%d
    ", step);
    
    
        return 0;
    }
    指针类型运算 使用案例
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 方式一:数组方式实现
    void my_strcpy01(char* dest, char* ch)
    {
        int i = 0;
        // 非0为真值
        while (ch[i])
        {
            dest[i] = ch[i];
            i++;
        }
        dest[i] = 0;
    }
    
    // 方式二:以指针偏移量
    void my_strcpy02(char* dest, char* ch)
    {
        int i = 0;
        while (*(ch+i))
        {
            *(dest + i) = *(ch + i);
            i++;
        }
        *(dest + i) = 0;
    }
    
    // 方式三:以指针运算方式实现
    void my_strcpy03(char* dest, char* ch)
    {
        while (*ch)
        {
            *dest = *ch;
            // 指针+1相当于指向数组下一个元素 内存地址变化了sizeof(char)
            dest++;
            ch++;
        }
        *dest = 0;
    }
    
    // 方式四:以指针加运算方式实现
    void my_strcpy04(char* dest, char* ch)
    {
        // 第一步:*ch 取值 *dest 取值
        // 第二部:*dest = *ch 赋值
        // 第三部:判断 值是否非0
        // 第四部:ch++ dest++
        while (*dest++ = *ch++);
    }
    
    int main(void)
    {
        // 指针运算、字符串拷贝
        char ch[] = "hello world";
        char dest[100];
        my_strcpy04(dest, ch);
        printf("%s
    ", dest);
    
        return 0;
    }
    指针类型运算 使用案例:指针加法运算
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    
    int main(void)
    {
        int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
        int* p = arr;
        
        // 指针的加减运算和指针的类型有关
        p = &arr[3];
        p--;
        p--;
        p--;
    
        // 内存地址相差:12 / sizeof(int) = 偏移量
        int step = p - arr;
    
        // 指针操作数组时下标允许时负数
        // p[-2] = *(p-2);
        printf("%d
    ", p[-2]);
        printf("%p
    ", p);
    
        return 0;
    }
    指针类型运算 使用案例:指针减法运算
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    
    int main(void)
    {
        // 指针和运算符的操作
        int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
        int* p = arr;
    
        // 野指针
        // p = p + arr; //err
        // p = p*arr; //err
        // p = p*4; //err
        // p = p/4; //err
        // p = p%4; //err
    
        // 指针判断可以使用、> = < ? && || ...
        // p = &arr[3]
        // if (p > arr) { printf("真
    ");}
    
        // 野指针可以相减
        // p = 100;
        // int step = arr - p;
        ///printf("%d
    ",step)
    
        return 0;
    }
    指针类型运算 使用案例:指针符号运算

    2、指针数组

    指针数组,它是数组,数组的每个元素都是指针类型。

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    
    int main(void)
    {
        // 定义数组 数据类型 数据名[元素个数] = {值1,值2}
        // 定义指针数组
        int a = 10;
        int b = 20;
        int c = 30;
        int* arr[3] = { &a,&b,&c };
    
        // arr[0]:为指针数组地址
        // *arr[0]:为指针对应值
        printf("%d
    ", arr[0]);
        printf("%d
    ", *arr[0]);
    
        for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
        {
            // 打印数组内每个值
            printf("%d
    ", *arr[i]);
        }
    
        // 指针数组大小 = 对应类型 * 元素个数 
        printf("指针数组大小:%d
    ", sizeof(arr));
        printf("指针数组大小:%d
    ", sizeof(arr[0]));
    
        return 0;
    }
    指针数组 使用案例
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    
    int main(void)
    {
        // 指针数组里面元素存储的是指针
        int a[] = { 1,2,3 };
        int b[] = { 4,5,6 };
        int c[] = { 7,8,9 };
    
        // 指针数组时一个特殊的二维数组模型
        // 指针数组对应于二级指针
        int* arr[] = { a,b,c };
    
        // 打印内存地址
        // arr 是指针数组的首地址
        printf("%p
    ", arr[0]);
        printf("%p
    ", a);
        printf("%p
    ", &a[0]);
    
    
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                // 通过二维数组方式打印所有值
                printf("%d", arr[i][j]);
                // 通过偏移量方式打印
                printf("%d", *(arr[i]+j));
                // 通过偏移量与指针运算方式打印
                printf("%d", *(*(arr + i) + j));
            }
            puts("");
        }
        return 0;
    }
    指针数组 使用案例:2
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    // 数组名做函数参数,函数的形参会退化为指针
    // 通过数组写法实现
    void my_strcat01(char* ch1, char* ch2)
    {
        int i = 0;
        while (ch1[i] != '')
        {
            i++;
        }
        int j = 0;
        while (ch2[j] != '')
        {
            ch1[i + j] = ch2[j];
            j++;
        }
        ch1[i + j] = 0;
    }
    
    // 通过指针加偏移量方式实现1
    void my_strcat02(char* ch1, char* ch2)
    {
        int i = 0;
        while (ch1[i] != '')
        {
            i++;
        }
        int j = 0;
        while (*(ch2 + j) != '')
        {
            *(ch1 + i + j) = *(ch2 + j);
            j++;
        }
        ch1[i + j] = 0;
    }
    
    // 通过指针加偏移量方式实现2
    void my_strcat03(char* ch1, char* ch2)
    {
        while (*ch1)ch1++;
        while (*ch1++ = *ch2++);
    }
    
    int main(void)
    {
        char ch1[100] = "hello";
        char ch2[] = "world";
        my_strcat02(ch1, ch2);
        printf("%s
    ", ch1);
    
        return 0;
    }
    指针数组 使用案例:数组名作为函数参数

    3、多级指针

    • C语言允许有多级指针存在,在实际的程序中一级指针最常用,其次是二级指针。
    • 二级指针就是指向一个一级指针变量地址的指针。
    • 三级指针基本用不着
    int a = 10;
    int *p = &a; //一级指针
    *p = 100; //*p就是a
     
    int **q = &p;
    //*q就是p
    //**q就是a
     
    int ***t = &q;
    //*t就是q
    //**t就是p
    //***t就是a

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    
    int main(void)
    {
        int a[] = { 1,2,3 };
        int b[] = { 4,5,6 };
        int c[] = { 7,8,9 };
        int* arr[] = { a,b,c };
    
        // 指针数组和二级指针建立关系
        int** p = arr;
    
        // 对应:arr[0][0]、a[0]
        printf("%d
    ", **p);
    
        // 二级指针加偏移量:相当于跳过了一个以为数组大小
        // 一级指针加偏移量:相当于跳过了一个元素
        //对应:arr[0][1]、a[1]
        printf("%d
    ", *(*p+1));
        //对应:arr[1][1]、b[1]
        printf("%d
    ", *(*(p + 1) + 1));
    
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                // 通过偏移量与指针运算方式打印
                printf("%d", *(*(arr + i) + j));
            }
            puts("");
        }
        return 0;
    }
    多级指针 使用案例
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
    
        //*ppp==**pp==&p
        //**ppp==*pp=p==&a
        //***ppp==**pp==*p=a
        int a = 10;
        int b = 20;
        int* p = &a;
        int** pp = &p;
        int*** ppp = &pp;
    
    
        // pp:二级指针变量的值
        // *pp:一级指针的值
        // **pp:变量的值
    
        // 等价于:p=&b
        // *pp = &b;
    
        // 等价于:a = 100
        //**pp = 100;
    
        // 野指针
        // *p = 100;
    
        printf("%d
    ", *p);
        return 0;
    }
    多级指针 使用案例:2

    4、字符指针

    字符指针通过指针处理字符

    案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 栈区字符串
        char ch[] = "hello world";
        
        // 数据区常量区字符串、不允许修改内容
        // hello world 对应内存地址为只读,大小相同
        char* p = "hello world";
        char* p1 = "hello world";
    
        // ch[2] = 'm'; // 可修改
        // p[2] = 'm'; //err
    
        return 0;
    }
    字符指针 使用案例
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 样式一
        // 可以做修改
        // 指针数组
        char ch1[] = "hello";
        char ch2[] = "world";
        char ch3[] = "dabaobei";
        char* arr1[] = { ch1,ch2,ch3 };
    
        // 样式二
        // 不能做修改、但可以排序
        // 字符串数组
        char* arr2[] = { "hello","wojjrld","zzzzz" };
    
        // 字符串排序
        for (int i = 0; i < 3 - 1; i++)
        {
            for (int j = 0; j < 3 - 1 - i; j++)
            {
                // 找首字符进行比较
                if (arr2[j][0]>arr2[j + 1][0])
                {
                    // 交换指针数组进行排序
                    char* temp = arr2[j];
                    arr2[j] = arr2[j + 1];
                    arr2[j + 1] = temp;
                }
            }
        }
    
        // 打印
        for (int i = 0; i < 3; i++)
        {
            printf("%s
    ", arr2[i]);
        }
        return 0;
    }
    字符指针 使用案例:2
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 数组实现
    int my_strlen01(char* ch)
    {
        // 计算字符串有效长度
        int i = 0;
        while (ch[i] != '')i++;
        return i;
    }
    
    // 指针实现
    int my_strlen02(char* ch)
    {
        char* temp = ch;
        while (*temp != '')temp++;
        return temp - ch;
    }
    
    int main(void)
    {
        char ch[] = "hello world";
        int len = my_strlen02(ch);
        printf("%d
    ", len);
        return 0;
    }
    字符指针 使用案例:字符指针作为函数参数

    三、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 指针作为函数参数传递
    void swap(int* a, int* b)
    {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    
    int main(void)
    {
    
        int a = 10;
        int b = 20;
    
        // 值传递
        // 形参不影响实参的值
        // swap(a, b);
    
        // 地址传递
        // 形参可以改变实参的值
        swap(&a, &b);
    
        printf("%d
    ", a);
        printf("%d
    ", b);
    
        return 0;
    }
    指针 使用案例:值传递和地址传递
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    void remove_space(char* ch)
    {
        // 便利字符串有效个数
        char* ftemp = ch;
        // 记录非空格字符串
        char* rtemp = ch;
        while (*ftemp)
        {
            if (*ftemp != ' ')
            {
                *rtemp = *ftemp;
                rtemp++;
            }
            ftemp++;
        }
        *rtemp = 0;
    }
    
    int main(void)
    {
        char ch[] = "  h  e  ll  o  w o r lld";
        remove_space(ch);
        printf("%s
    ", ch);
        return 0;
    }
    指针 使用案例:字符串去空格
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 数组方式
    char* my_strchr01(char* str,char ch)
    {
        int i = 0;
        while (str[i])
        {
            if (str[i] == ch)
            {
                return &str[i];
            }
            i++;
        }
        return NULL;
    }
    
    // 指针方式
    char* my_strchr02(char* str, char ch)
    {
        while (*str)
        {
            if (*str == ch)
            {
                return str;
            }
            str++;
        }
        return NULL;
    }
    
    int main(void)
    {
        char str[] = "hello world";
        char* p = my_strchr02(str,'w');
        if (p == NULL)
        {
            printf("未找到:");
        }
        printf("%s
    ", p);
        return 0;
    }
    指针 使用案例:指针做为函数的返回值
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    char* my_strchr(char* src, char* dest)
    {
        // 用于循环便利源字符串指针
        char* fsrc = src;
        // 记录每次相同字符串首地址
        char* rsrc = src;
        char* tdest = dest;
        while (*fsrc)
        {
            rsrc = fsrc;
            while (*fsrc == *tdest && *fsrc!='')
            {
                fsrc++;
                tdest++;
            }
            if (*tdest == '')
            {
                return rsrc;
            }
            // 回滚
            // 目标字符串更新到起始位置
            tdest = dest;
            fsrc = rsrc;
            fsrc++;
        }
        return NULL;
    }
    
    int main(void)
    {
        char src[] = "hello world";
        char dest[] = "llo";
        char* p = my_strchr(src,dest);
        printf("%s
    ", p);
        return 0;
    }
    指针 使用案例:模糊查询
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 数组实现
    int getstrcount01(char* ch)
    {
        int i = 0;
        int count = 0;
        while (ch[i])
        {
            if (ch[i] != ' ')
            {
                count++;
            }
            i++;
        }
        return count;
    }
    
    // 指针实现
    int getstrcount02(char* ch)
    {
        int count = 0;
        while (*ch)
        {
            if (*ch != ' ')count++;
            ch++;
        }
        return count;
    }
    
    int main(void)
    {
        char ch[] = "    hello world    ";
        int len = getstrcount(ch);
        printf("%d
    ", len);
        return 0;
    }
    指针 使用案例:求非空字符串元素的个数
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        //97+26 ASCLL码 
        // 统计字符串出现次数
        char ch[] = "helloworldfdjklfdjklfdsajklfdsa dsa";
        
        // 存储字符串出现次数
        int arr[26] = {0};
        
        for (int i = 0; i < strlen(ch); i++)
        {
            // ASCLL码 a - 字符、++:每找到一个相同就+1
            arr[ch[i] - 'a']++;
        }
    
        for (int i = 0; i < 26; i++)
        {
            if(arr[i])
                printf("字母:%c出现次数:%d
    ", i + 'a', arr[i]);
        }
        return 0;
    }
    指针 使用案例:统计字符个数
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    // 数组实现
    void inverse01(char* ch)
    {
        int i = 0;
        int j = strlen(ch) - 1;
        while (i < j)
        {
            char temp = ch[i];
            ch[i] = ch[j];
            ch[j] = temp;
            i++;
            j--;
        }
        return;
    }
    
    // 指针实现
    void inverse02(char* ch)
    {
        char* ftemp = ch;
        char* btemp = ch + strlen(ch) - 1;
        while (ftemp<btemp)
        {
            char temp = *ftemp;
            *ftemp = *btemp;
            *btemp = temp;
            ftemp++;
            btemp--;
        }
        return;
    }
    
    int main(void)
    {
        char ch[] = "hello world";
        inverse02(ch);
        printf("%s
    ", ch);
        return 0;
    }
    指针 使用案例:字符串逆质
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int symm(char* ch)
    {
        char* ftemp = ch;
        char* btemp = ch + strlen(ch) - 1;
        while (ftemp < btemp)
        {
            if (*ftemp!=*btemp)
            {
                return 1;
            }
            ftemp++;
            btemp--;
        }
        return 0;
    }
    
    // 判断:回文字符串
    int main(void)
    {
        char ch[] = "abcba";
        int value = symm(ch);
        if (!value)
        {
            printf("相同
    ");
        }
        else
        {
            printf("不相同
    ");
    
        }
        return 0;
    }
    指针 使用案例:判断回文字符串
  • 相关阅读:
    XML及XML的解析
    单例设计模式(Singleton)的优化
    Java反射初识
    TCP协议的简单应用一
    Java中实现线程同步的三种方法
    Java集合框架Map接口
    JDK1.8新特性之Stream类初识
    Java JDK1.8新特性之四大函数式接口
    tomcat 启动报 找不到 StrutsPrepareAndExecuteFilter。。
    easyjweb ejs 2014.2.25
  • 原文地址:https://www.cnblogs.com/xiangsikai/p/12378091.html
Copyright © 2011-2022 走看看