• C语言学习6 :指针的定义,指针类型要合法,指针要初始化,指针做函数参数,数组和指针的通用性,指针+1所代表的空间,void * 指针,交换函数中的指针,数组和字符型指针区别,字符型指针的应用,使用指针完成字符操作函数


    1,指针的基本用法1

    #include <stdio.h>
    
    // 指针和数组都是复合类型, 他们从基本类型
    // 或者自定义类型派生.
    
    int main(void)
    {
        // 当定义指针变量p 时, int * --> 这里的 *
        // 不是运算符, 而是 类型定义说明符.
    
        // 定义了一个变量p
        // p 是 int * 类型. p 指向 int 类型.
        int *p = NULL; 
        int a = 8;
    
        // 此时, p 指向 a
        p = &a;
    
        printf("sizeof p = %u
    ", sizeof(p));
        printf("&p = %p, p = %p
    ", &p, p);
        printf("&a = %p, a = %d
    ", &a, a);
        printf("====================
    ");
    
        // * 是一个运算符. 称解引用运算符 / 间接访问运算符
        *p = 16;
        printf("a = %d, *p = %d
    ", a, *p);
    
        printf("--------------------
    ");
    
        // [] 是一个运算符. 按索引解引用 / 按索引间接访问.
        p[0] = 32;
        printf("a = %d, *p = %d
    ", a, *p);
    
        return 0;
    }

    结果:

    will@will-Inspiron-N4010:~/c/5th$ ./a.out
    sizeof p = 4
    &p = 0xbf8b9f18, p = 0xbf8b9f1c
    &a = 0xbf8b9f1c, a = 8
    ====================
    a = 16, *p = 16
    --------------------
    a = 32, *p = 32

    2,指针的基本用法2

    #include <stdio.h>
    
    int main(void)
    {
        unsigned long p = 0;
        int a = 8;
    
        // &a 的结果是一个 int * 类型的指针值
        // 将其转换为 unsigned long, 去除编译器警告
        // 之后, 变量p 中存放了 变量a 的地址.
        p = (unsigned long)&a;
    
        // 类型决定类型之上的操作是否合法
        // 所以, 将 p 强制转换为 int * 类型,
        // 那么对 p 进行解引用运算就合法了.
        *(int *)p = 16;
    
        printf("a = %d, *p = %d
    ", a, *(int *)p);
    
        return 0;
    }

    结果:(int *)这个是作为定义的存在,相当于int *p

    a = 16, *p = 16

    3,指针基本用法3

    #include <stdio.h>
    
    int main(void)
    {
        // 未初始化的指针称为野指针
        // dangling pointer
        int *p;
    
        printf("p = %p
    ", p);
    
        *p = 345;
    
        printf("*p = %d
    ", *p);
    
        return 0;
    }

    结果:未初始化的指针无法直接赋值。

    p = 0xb77b3ff4
    Segmentation fault (core dumped)
    4,指针做函数参数

    #include <stdio.h>
    
    void rand_a(int *p, int len)
    {
        int i;
        for (i = 0; i < len; i++)
            // *(p + i) = rand() % 100;
            p[i] = rand() % 100;
    }
    
    void print_a(int *p, int len)
    {
        int i;
        for (i = 0; i < len; i++)
            printf("%d ", *(p + i));
        putchar('
    ');
    }
    
    int main(void)
    {
        int a[10];
    
        rand_a(a, 10);
    
        print_a(&a[0], 10);
    
        return 0;
    }

    结果:数组传入是int a[ ],指针形式传入是int *a  都是传入数组首地址,两者可通用

    will@will-Inspiron-N4010:~/c/5th$ ./a.out
    83 86 77 15 93 35 86 92 49 21 

    5,数组和指针的通用性

    #include <stdio.h>
    
    void rand_a(int *p, int len)
    {
        int i;
        for (i = 0; i < len; i++)
            *(p + i) = rand() % 100;
    }
    
    void print_a(int *p, int len)
    {
        int i;
        for (i = 0; i < len; i++)
            printf("%d ", *(p + i));
        putchar('
    ');
    }
    
    int max(int *p, int len)
    {
        int i;
        int max = *p;
    
        for (i = 0; i < len; i++)
        {
            if (*(p + i) > max)    
                max = *(p + i);
        }
    
        return max;
    }
    
    int min(int *p, int len)
    {
        int i;
        int min = *p;
    
        for (i = 0; i < len; i++)
        {
            if (*(p + i) < min)    
                min = *(p + i);
        }
    
        return min;
    }
    
    void __move_left(int *p, int len)
    {
        int i;
        int t = *p;
    
        for (i = 0; i < len - 1; i++)
            *(p + i) = *(p + i + 1);
    
        *(p + i) = t;
    }
    
    void move_left(int *p, int len, int shift)
    {
        int i;
        shift %= len;
        for (i = 0; i < shift; i++)
            __move_left(p, len);
    }
    
    void __move_right(int *p, int len)
    {
        int i;
        for (i = len - 1; i > 0; i--)
        {
            *(p + i) ^= *(p + i - 1);    
            *(p + i - 1) ^= *(p + i);
            *(p + i) ^= *(p + i - 1);    
        }
    }
    
    void move_right(int *p, int len, int shift)
    {
        int i;
        shift %= len;
        for (i = 0; i < shift; i++)
            __move_right(p, len);
    }
    
    void reverse(int *p, int len)
    {
        int i;
        for (i = 0; i < len / 2; i++)
        {
            *(p + i) ^= *(p + len - i - 1);    
            *(p + len - i - 1) ^= *(p + i);
            *(p + i) ^= *(p + len - i - 1);    
        }
    }
    
    void bubble_sort(int *p, int len)
    {
        int i, j;
        for (i = 0; i < len - 1; i++)
        {
            for (j = 0; j < len - i - 1; j++)    
            {
                if (*(p + j) > *(p + j + 1))    
                {
                    *(p + j) ^= *(p + j + 1);    
                    *(p + j + 1) ^= *(p + j);
                    *(p + j) ^= *(p + j + 1);    
                }
            }
        }
    }
    
    int main(void)
    {
        int a[10];
    
        rand_a(a, 10);
        print_a(a, 10);
    
        printf("max: %d
    ", max(a, 10));
        printf("min: %d
    ", min(a, 10));
    
        printf("move left 3:
    ");
        move_left(a, 10, 3);
        print_a(a, 10);
    
        printf("move right 3:
    ");
        move_right(a, 10, 3);
        print_a(a, 10);
    
        printf("reverse:
    ");
        reverse(a, 10);
        print_a(a, 10);
    
        printf("sort:
    ");
        bubble_sort(a, 10);
        print_a(a, 10);
    
        return 0;
    }

    结果和前一章节的数组变换一样。只不过是p[i]  替换成*(p+i)而已,p是首地址。

    6,指针在内存中的使用

    #include <stdio.h>
    
    int main(void)
    {
        int *p = NULL;
        char *pch = NULL;
        int a = 0x55667788;
    
        p = &a;
        pch = (char *)p;
    
        printf("p = %p, pch = %p, &a = %p
    ", p, pch, &a);
    
        // 指针指向的类型决定了其 + 1, 地址 + 多少字节.
        printf("p + 1 = %p, pch + 1 = %p
    ", p + 1, pch + 1);
    
        // 同时, 指针指向的类型决定了 *p 从指针指向的地址取出多少(字节)内容.
        printf("*p          = %#x
    ", *p);
    
        // 打印时, 隐式类型转换, 符号扩展
        printf("*pch        = %#x
    ", *pch);
        printf("*pch + 1    = %#x
    ", *(pch + 1));
        printf("*pch + 2    = %#x
    ", *(pch + 2));
        printf("*pch + 3    = %#x
    ", *(pch + 3));
    
        return 0;
    }

    结果:

    will@will-Inspiron-N4010:~/c/5th$ ./a.out
    p = 0xbfb39104, pch = 0xbfb39104, &a = 0xbfb39104
    p + 1 = 0xbfb39108, pch + 1 = 0xbfb39105
    *p          = 0x55667788
    *pch        = 0xffffff88
    *pch + 1    = 0x77
    *pch + 2    = 0x66
    *pch + 3    = 0x55

     7,void * 指针

    #include <stdio.h>
    
    int main(void)
    {
        int *p = NULL;
        void *pv = NULL;
    
        int a = 0x11223344;
    
        p = &a;
    
        // void * 类型和任意指针类型 类型兼容
        pv = p;
    
        printf("p = %p, pv = %p, &a = %p
    ", p, pv, &a);
        // void * 类型指针 + 1, 地址 + 1(字节).
        printf("p + 1 = %p, pv + 1 = %p
    ", p + 1, pv + 1);
    
        printf("------------------
    ");
        printf("a = %#x, *p  = %#x
    ", a, *p);
    
        // void * 类型不允许解引用.
        printf("a = %#x, *pv = %#x
    ", a, *(int *)pv);
    
        return 0;
    }

    结果:不允许直接使用*pv必须转换,所以就有了int *的定义。

    p = 0xbfacdad4, pv = 0xbfacdad4, &a = 0xbfacdad4
    p + 1 = 0xbfacdad8, pv + 1 = 0xbfacdad5
    ------------------
    a = 0x11223344, *p  = 0x11223344
    a = 0x11223344, *pv = 0x11223344

    8,交换函数中指针的作用

    #include <stdio.h>
    
    void swap1(int a, int b)
    {
        int t;
        t = a;
        a = b;
        b = t;
    }
    
    void swap2(int *a, int *b)
    {
        int t;
        t = *a;
        *a = *b;
        *b = t;
    }
    
    int main(void)
    {
        int a = 3, b = 5;
    
        printf("a = %d, b = %d
    ", a, b);
    
        swap1(a, b);
        printf("---after swap1---
    ");
        printf("a = %d, b = %d
    ", a, b);
    
        swap2(&a, &b);
        printf("---after swap2---
    ");
        printf("a = %d, b = %d
    ", a, b);
    
        return 0;
    }

    结果:效果是一样的,给了地址交换。

    a = 3, b = 5
    ---after swap1---
    a = 3, b = 5
    ---after swap2---
    a = 5, b = 3

    9,数组和字符型指针的区别

    #include <stdio.h>
    
    int main(void)
    {
        // 数组初始化, 字符存放在 str 数组中.
        char str[128] = "china unix";
    
        // 将字符串的首地址给予指针变量 s
        // 字符串本身存放于 .rodata 段.
        char *s = "china unix";
    
        printf("str = %s
    ", str);
        str[2] = 'I';
        printf("str = %s
    ", str);
    
        printf("----------------------------
    ");
    
        printf("s = %s
    ", s);
        // 段错误.(试图修改只读数据段的数据)
        s[2] = 'I';
        printf("s = %s
    ", s);
    
        return 0;
    }

    结果:数组可改,字符型指针不可更改

    str = china unix
    str = chIna unix
    ----------------------------
    s = china unix
    Segmentation fault (core dumped)

    10,字符型指针应用

    #include <stdio.h>
    
    int main(void)
    {
        char *s = "012345ABCDEF";
    
        printf("s[6] = %c
    ", s[6]);
    
        printf("-----------------
    ");
    
        printf(""012345ABCDEF"[6] = %c
    ", "012345ABCDEF"[6]);
        printf("*("012345ABCDEF" + 6) = %c
    ", *("012345ABCDEF" + 6));
    
        return 0;
    }

    结果:其实效果一样

    s[6] = A
    -----------------
    "012345ABCDEF"[6] = A
    *("012345ABCDEF" + 6) = A

    11,使用指针完成字符操作函数

    #include <stdio.h>
    
    int my_strlen(char *s)
    {
        int i = 0;
    
        while (*(s + i) != '')
            i++;
        return i;
    }
    
    int my_strlen_recur(char *s)
    {
        if (*s == '')
            return 0;
    
        return 1 + my_strlen_recur(++s);
    }
    
    char *my_strcpy(char *dst, const char *src)
    {
        char *dst_old = dst;
    
        while ((*dst++ = *src++) != '')
            ;
        return dst_old;
    }
    
    char *my_strcat(char *dst, const char *src)
    {
        char *dst_old = dst;
    
        /*
         * dst --> ''后一字符
         * while (*dst++ != '')
         *    ;
         */
    
        // dst --> ''
        while (*dst != '')
            dst++;
    
        while ((*dst++ = *src++) != '')
            ;
    
        return dst_old;
    }
    
    int my_strcmp(const char *s1, const char *s2)
    {
        while (*s1 == *s2 && *s1 != '')
            s1++, s2++;
    
        return *s1 - *s2;
    }
    
    char *my_strchr(const char *s, int c)
    {
        while (*s != '')
        {
            if (*s == c)    
                return (char *)s;
            s++;
        }
    
        return NULL;
    }
    
    char *my_strstr(const char *s, const char *substr)
    {
        const char *start_cmp = NULL, *substr_start = substr;
    
        while (*s != '')
        {
            start_cmp = s, substr = substr_start;
            while (*s == *substr && *s != '')
                s++, substr++;
    
            if (*substr == '')
                return (char *)start_cmp;
    
            s = start_cmp;
            s++;
        }
    
        return NULL;
    }
    
    int main(void)
    {
        char s1[128];
        char s2[128];
    
        printf("test strlen, input s1:");
        gets(s1);
        printf("len of s1 is %d
    ", my_strlen(s1));
    
        printf("test strcpy, input s1: ");
        gets(s1);
        my_strcpy(s2, s1);
        printf("s2: %s
    ", s2);
    
        printf("test strcat, input s1: ");
        gets(s1);
        my_strcat(s2, s1);
        printf("s2: %s
    ", s2);
    
        printf("test strcmp, input s1: ");
        gets(s1);
        printf("test strcmp, input s2: ");
        gets(s2);
        if (strcmp(s1, s2) > 0)
            printf("%s > %s
    ", s1, s2);
        else if (strcmp(s1, s2) < 0)
            printf("%s < %s
    ", s1, s2);
        else
            printf("%s == %s
    ", s1, s2);
    
        int ch;
        char *index = NULL;
        printf("test strchr, input s1: ");
        gets(s1);
        printf("input ch: ");
        ch = getchar();
        if ((index = my_strchr(s1, ch)) != NULL)
            printf("%s has %c, index = %d
    ", s1, ch, index - s1);
        else
            printf("not find.
    ");
    
        while (getchar() != '
    ')
            ;
    
        printf("test strstr, input s1: ");
        gets(s1);
        printf("input s2: ");
        gets(s2);
        if ((index = my_strstr(s1, s2)) != NULL)
            printf("%s has %s, index = %d
    ", s1, s2, index - s1);
        else
            printf("not find.
    ");
    
        return 0;
    }

    结果:

    test strlen, input s1:wang
    len of s1 is 4
    test strcpy, input s1: apk
    s2: apk
    test strcat, input s1: apk
    s2: apkapk
    test strcmp, input s1: what
    test strcmp, input s2: whaa
    what > whaa
    test strchr, input s1: what
    input ch: a
    what has a, index = 2
    test strstr, input s1: what2222at
    input s2: at
    what2222at has at, index = 2
  • 相关阅读:
    html5基础知识------全局属性
    css3盒模型 box-sizing
    AFO
    关于线段树的一个模板
    从头整理一下
    搜索?
    一些好的文章
    网络流初步学习之最大流
    NOIP2014 D1T3 [洛谷P1941] 飞扬的小鸟
    [洛谷P5259] 游戏中的学问
  • 原文地址:https://www.cnblogs.com/will-boot/p/3301402.html
Copyright © 2020-2023  润新知