zoukankan      html  css  js  c++  java
  • 《彻底搞定C指针》文档整理

    一.变量存储

     #include <stdio.h>
     int main(void)
     {
         int i = 39;
         printf(“%d
    ”, i); 
         printf(“%d
    ”, &i); //十进制打印i的地址
         printf(“%x
    ”, &i); //十六进制打印i的地址 
         return(0);
    }
    /*得到结果:
    ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
    39
    23300652
    1638a2c
    ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
    39
    1367552540
    5183321c
    ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
    39
    1684339276
    6464fa4c
    每次得到的地址都不同*/

    二. 什么是指针

    #include <stdio.h>
    int main(void)
    {
        char a, *pa;
        a = 10;
        pa = &a; /* pa指向变量a的地址 */
        *pa = 20; /* 给变量a的地址的内容赋值为20, 即a=20*/
        printf("%d
    ", a);
    }
    /* 得到结果: 20 */

    三. 指针与数组名

    #include <stdio.h>
    int main(void)
    {
        int i, *pa, a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        //int * const pa = a; //不行, pa被定义为常量指针了
        pa = a;
        
        printf("array mode:
    ");
        for(i = 0; i < 10; i++)
            printf("%d ", a[i]);
        printf("
    pointer mode:
    ");
        for(i = 0; i < 10; i++)
            printf("%d ", *(a+i));
        printf("
    
    ");
        for(i = 0; i < 10; i++)
            printf("%d ", pa[i]);
        printf("
    ");
        for(i = 0; i < 10; i++)
            printf("%d ", *(pa+i));
        printf("
    ");
        for(i = 0; i < 10; i++)
        {    
            printf("%d ", *pa);
            pa++;
        }    
        printf("
    ");
        return 0;
    }
    /*执行后显示:
    array mode:
    0 1 2 3 4 5 6 7 8 9 
    pointer mode:
    0 1 2 3 4 5 6 7 8 9 
    
    0 1 2 3 4 5 6 7 8 9 
    0 1 2 3 4 5 6 7 8 9 
    0 1 2 3 4 5 6 7 8 9   
    */

    四. const int *pi与int *const pi的区别

    #include <stdio.h>
    int main(void)
    {    
        int i1 = 30, i2 = 40;
        const int *pi = &i1;
        pi = &i2; /* 注意这里, pi 可以在任意时候重新赋值一个新内存地址*/
        i2 = 80; /* 这里能用*pi = 80 来代替吗?当然不能! */ 
        printf("%d
    ", *pi); /* 输出是 80 */
        return 0;
    }
    /*pi 的值是可以被修改的。即它可以重新指向另一个地址的,但是,不能通过*pi 来修改 i2 的值*/
    #include <stdio.h>
    int main(void)
    {    
        int i1 = 30, i2 = 40;
        int *const pi = &i1;
        /* pi = &i2; 注意这里, pi 不能再这样重新赋值了,即不能再指向另一个新地址 */
        i1 = 80; /* 这里能用 *pi = 80; 来代替吗?可以,这里可以通过*pi 修改 i1 的 */ 
        printf("%d
    ", *pi); /* 输出是 80 */
        return 0;
    }
    /*pi 的值是可以被修改的。即它可以重新指向另一个地址的,但是,不能通过*pi 来修改 i2 的值*/

    总结:

    1) 如果 const 修饰在*pi 前,则不能改的是*pi(即不能类似这样: *pi=50;赋值)而不是指 pi。
    2) 如果 const 是直接写在 pi 前,则 pi 不能改(即不能类似这样:pi=&i; 赋值)。

    五. 函数参数的传递

    Q1. 值传递

    #include <stdio.h>
    void Exchg1(int x, int y)
    {
        int tmp;
        tmp = x;
        x = y;
        y = tmp;
        printf("x = %d, y = %d
    ", x, y);
    }
    
    int main(void)
    {
        int a = 4, b = 6;
        Exchg1(a, b);
        printf("a = %d, b = %d
    ", a, b);    
        return 0;
    }
    /*编译执行,输出:
    x = 6, y = 4
    a = 4, b = 6
    */

    Q2. 地址传递

    #include <stdio.h>
    void Exchg2(int *px, int *py)
    {
        int tmp = *px;
        *px = *py;
        *py = tmp;
        printf("*px = %d, *py = %d
    ", *px, *py);
    }
    
    int main(void)
    {
        int a = 4, b = 6;
        Exchg2(&a, &b);
        printf("a = %d, b = %d.
    ", a, b);    
        return 0;
    }
    /*编译执行,输出:
    *px = 6, *py = 4
    a = 6, b = 4
    */

    Q3. 引用传递

    #include <stdio.h>
    void Exchg3(int &x, int &y) /* 注意定义处的形式参数的格式与
    值传递不同 */
    {
        int tmp = x;
        x = y;
        y = tmp;
        printf("x = %d, y = %d.
    ", x, y);
    }
    
    main()
    {
        int a = 4;
        int b = 6;
        Exchg3(a, b); /*注意:这里调用方式与值传递一样*/
        printf("a = %d, b = %d.
    ", a, b);
    }
    /*编译报错,因为C没有引用的用法,C++才*/

    六. 指向另一指针的指针

    #include <stdio.h>
    void find1(char array[], char search, char **ppa)
    {
        int i;
        for(i = 0; *(array + i) != 0; i++)
        {
            if(*(array + i) == search)
            {
                *ppa = array + i;
                break;
            }
            else if(*(array + i) == 0)
            {
                *ppa = 0;
                break;
            }
        }
    }
    
    int main(void)
    {
        char str[] = {"afsdfsdfdf"};
        char a = 'd';
        char *p = 0;
        find1(str, a, &p);
        if(0 == p)
            printf("没找到!
    ");
        else
            printf("找到了,p = %x
    ", p);
        return 0;
    }
    /*编译执行,输出:
    找到了,p = 6393eb53
    */

    七. 函数名与函数指针

     1.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    void (*FunP)(int); //也可写成void (*FunP)(int x)
    int main(int argc, char* argv[])
    {
        MyFun(10);
        FunP = &MyFun;
        (*FunP)(20);
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出:
    10
    20
    */

    2.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    void (*FunP)(int); //也可写成void (*FunP)(int x)
    int main(int argc, char* argv[])
    {
        MyFun(10);
        FunP = MyFun;
        FunP(20);
        return 0;
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出:
    10
    20
    */

    3.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    void (*FunP)(int); //也可写成void (*FunP)(int x)
    int main(int argc, char* argv[])
    {
        MyFun(10);
        FunP = &MyFun;
        FunP(20);
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出:
    10
    20
    */

    4.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    void (*FunP)(int); //也可写成void (*FunP)(int x)
    int main(int argc, char* argv[])
    {
        MyFun(10);
        FunP = MyFun;
        (*FunP)(20);
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出
    10
    20
    */

    5.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    void (*FunP)(int); //也可写成void (*FunP)(int x)
    int main(int argc, char* argv[])
    {
        (*MyFun)(10);
        FunP = &MyFun;
        (*FunP)(20);
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出:
    10
    20
    */

    总结上面: 1)  其实, MyFun 的函数名与 FunP 函数指针都是一样的, 即都是函数指针。 MyFun 函数名是一个函数指针常量,而 FunP 是一个函数数指针变量,这是它们的关系。
    2)  但函数名调用如果都得如(*MyFun)(10)这样,那书写与读起来都是不方便和不习惯的。所以 C 语言的设计者们才会设计成又可允许 MyFun(10)这种形式地调用(这样方便多了并与数学中的函数形式一样,不是吗?)。
    3)  为统一起见, FunP 函数指针变量也可以 FunP(10)的形式来调用。
    4)  赋值时,即可 FunP = &MyFun 形式,也可 FunP = MyFun。

    6.

    #include <stdio.h>
    void MyFun(int x); //也可写成void MyFun(int)
    typedef void (*FunType)(int);
    FunType FunP;
    int main(int argc, char* argv[])
    {
        //FuncType FunP;/*函数指针变量也可以是局部的*/
        MyFun(10);
        FunP = &MyFun;
        FunP(20);
        return 0;
    }
    
    void MyFun(int x)
    {
        printf("%d
    ", x);
    }
    /*编译执行,输出:
    10
    20
    */

    7.

    #include <stdio.h>
    void MyFun1(int x);
    void MyFun2(int x);
    void MyFun3(int x);
    typedef void (*FunType)(int);
    void CallMyFun(FunType fp, int x);
    int main(int argc, char* argv[])
    {
        CallMyFun(MyFun1, 10);    
        CallMyFun(MyFun2, 20);
        CallMyFun(MyFun3, 30);
    }
    
    void CallMyFun(FunType fp, int x)
    {
        fp(x);
    }
    
    void MyFun1(int x)
    {
        printf("函数MyFun1中输出:%d
    ", x);
    }
    
    void MyFun2(int x)
    {
        printf("函数MyFun2中输出:%d
    ", x);
    }
    
    void MyFun3(int x)
    {
        printf("函数MyFun3中输出:%d
    ", x);
    }
    /*
    函数MyFun1中输出:10
    函数MyFun2中输出:20
    函数MyFun3中输出:30
    */
  • 相关阅读:
    1 TKinter小窗口及标题
    css之padding,marging
    css之opacity
    css之position
    Leetcode 1368 使网格图至少有一条有效路径的最小代价
    Leetcode 137 只出现一次的数字II
    Leetcode 135分发糖果
    Leetcode 134加油站
    Leetcode 124 二叉树的最大路径和
    Leetcode 5346 二叉树中的列表
  • 原文地址:https://www.cnblogs.com/try-again/p/5166561.html
Copyright © 2011-2022 走看看