C语言指针笔记

作者: CrazySteven | 来源:发表于2017-05-22 17:36 被阅读649次

    由于做算法题都用的C语言,就找时间补习了一下指针,看的书是《指针的艺术》,作者是蔡明志,把书中的经典题拿出来做个笔记,做个备份

    ++和*具有相同的运算优先级,但结合性是由右至左的。

        int i[] = {10,20,30,40,50};
        int *pa[] = {i, i+2, i+1, i+4, i+3};
        int **p2 = pa;//**p2为10
        p2++;//**p2为30
        ++*p2;//**p2为40
        **p2++;//**p2为20
        ++**p2;//**p2为21
    

    第一句注释不解释了。
    第二句p2++是将p2右移一位,移到i+2,即30
    第三句++*p2根据结合性可看做++(*p2),*p2是指向i+2(30)的指针,将地址向下移一位便到了40(i中的地址是连续的)
    第四句**p2++根据结合性可以看做**(p2++),由于++在后面,执行顺序又变成了(*(*p2)++),上面说过*p2指向i+2,右移一位是i+1,再取值为20
    第五句++**p2根据结合性看做++(**p2),**p2为20,++后为21


        char *s[] = {"Stanford", "University", "California", "America"};
        char **sa[] = {s, s+1, s+2, s+3};
        char ***p3 = sa;
        printf("**p3++ = %s\n",**p3++);//Stanford
        printf("**++p3 = %s\n",**++p3);//California
        printf("**++*p3 = %c\n",**++*p3);//A
        printf("*(*--*++p3+3) = %c\n",*(*--*++p3+3));//i
    

    可以看做是char s[4][10]
    第一句**p3++++在后面,先执行**p3,就是Stanford,然后++,下移指向U
    第二句**++p3,先++,下移指向C,**输出字符串California
    第三句**++*p3,同第二句,也是将其下移,和第二句的区别是***是取元素的内容,**是指针,故第二句输入的是字符串,第三句输出的是字符
    第四句*(*--*++p3+3)比较长,慢慢来分析,*++p3下移指向A,*--*++p3上移指向C,*--*++p3+3此时已经有两个*,故+3是向右移3个位置,是指向i的指针,*(*--*++p3+3)3个*则是取元素i


    下面这个例子比较经典的展示了传值调用和传址调用的效果。。。

    void swap_by_value(int a,int b) {
        int temp = a;
        a = b;
        b = temp;
    }
    
    void swap_by_address(int *a, int *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    
    int main() {
        int x = 100,y = 200;
        printf("before:x = %d,y = %d\n",x,y);//x = 100,y = 200;
        swap_by_value(x,y);
        printf("after:x = %d,y = %d\n",x,y);//x = 100,y = 200;
        
        x = 100; y = 200;
        printf("before:x = %d,y = %d\n",x,y);//x = 100,y = 200;
        swap_by_address(&x, &y);
        printf("after:x = %d,y = %d\n",x,y);//x = 200,y = 100;
    }
    

    下面这是一个改错题

    //n为5
    int *pf(int x[5],int n) {
        int m;
        int k[5];
        int j[] = {1,2,3};
        for (m = 0; m < 5;m++) {
            k[m] = j[m]+ x[m];
        }
        return k;
    }
    

    此题的主要问题在int k[5]这句话应该放在函数外面,局部变量会被销毁,变成野指针。。。


    几个容易混淆的:
    int (*p)[11]:p是指向含有11个元素数组的指针
    int *p[1]:p是数组,含有11个元素,每一元素均为指向int型的指针
    int **p;p是一个二重指针,需经两次的间接访问才能得到整数变量值
    int(*p)(int):p是指向函数的指针,此函数含有int参数,返回值的数据类型为int
    int *p(int):p是函数,此函数有一个int型参数,并返回一个指向int的指针


    //计算字符串长度(strlen)
    int stringLength(char *) {
        int t = 0;
        while(*p != '\0') {
            t++;
            p++;
        }
    }
    
    //复制字符串(strcpy),需注意传进来dest的内存够不够大
    void myStringCopy(char *dest,char *source) {
        while((*dest = *source) != '\0') {
            source++;
            dest++;
        }
    }
    
    //拼接字符串(strcat),同样需要注意传进来的dest内存够不够大
    void stringConcate(char *dest,char *source) {
        while(*dest != '\0') dest++;
        while((*dest = *source) != '\0') {
            source++;
            dest++;
        }
    }
    
    //拼接前n个字符到字符串(strncat),注意dest内存
    void stringConcate_n(char *dest,char *source,int n) {
        int i = 1;
        while(*dest != '\0') dest++;
        while (i <= n && (*dest = source) != '\0') {
            source++;
            dest++;
            i++;
        }
    }
    
    //字符串比较(strcmp:0相等,1(正数)大于,-1(负数)小于)顺便在此说明以下,判断字符是否相等直接使用==即可,==表示判断地址是否一样,而不是内容,当然,地址一样内容一定一样,但内容一样地址不一定是一样的
    int stringCompare(char *x,char *y) {
        for( ; *x == *y; x++,y++) {
            if (*x == '\0') return 0;
        }
        return *x - *y;
    
    //比较字符串的前n位(strncmp)
    int stringCompare_n(char *x,char *y, int n) {
        for (int i = 1; (*x == *y) || i <= n; x++,y++) {
            if (*x == '\0') return 0;
        }
        return *x - *y;
    
    //关于结构体的指针(第一段)
    struct student {
            char *name;
            int scrore;
        };
        
        struct student st = {"Brian",97};
        struct student *ptr = &st;
        
        printf("ptr->name = %s\n",ptr->name);//Brian
        printf("*ptr->name = %c\n",*ptr->name);//B
        printf("*ptr->name++ = %c\n",*ptr->name++);//B
        printf("*ptr->name = %c\n",*ptr->name);//r
        printf("*ptr->score = %d\n",ptr->scrore);//97
        printf("*ptr->score++ = %d\n",(ptr->scrore)++);//97
        printf("*ptr->sco = %d\n",ptr->scrore);//98
    //关于结构体的指针(第二段)
    struct student_new {
            char name[20];
            int scrore;
        };
        
        struct student_new st = {"Brian",97};
        struct student_new *ptr = &st;
        
        printf("*ptr->name = %c\n",++*(ptr->name));//C
        //在结构体中,如果是一般变量,则用.调用,若是指针变量,则用->调用,也可用*调用,如上例(*student).name
    

    最后是链表,由于之前的算法题已经涉及过链表,我在这里就不说了,这本书上介绍的也就是创建及增删改查之类。

    本书我只看了前8章,因为从第九章开始就讲的是C++/C#/JAVA之类的,所以笔记就到这里了。

    版权声明:本文为 Crazy Steven 原创出品,欢迎转载,转载时请注明出处!

    相关文章

      网友评论

        本文标题:C语言指针笔记

        本文链接:https://www.haomeiwen.com/subject/xvkixxtx.html