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

    我是搞java的,今年要找工作,参加笔试就必须要准备一些C/C++、算法、数据结构、操作系统、概率论的东西,浅谈一下我作为初学者对C指针的学习和理解。

    一、*p 概念:

    申明一个整形指针变量:

    int * pi;

    pi是一个指针,pi存的是地址编号的变量,若 int *pi = i; 则pi=&i;有下面等式:&(*pi)=pi;

    例:

    int a,*pa;
    a=10;
    pa=&a;
    *pa=20;
    printf( “%d”, a) //输出20;通过改变指针pa所指的内容来改变a的值,其实pa=&a;操作使pa和&a指向同一个内容。

    二、指针和数组:

    当一个指针变量被初始化成数组名时,就说该指针变量指向了数组。如:

      char str[20], *ptr;

      ptr=str;  //ptr被置为数组str第一个元素的地址(ptr=&str[0]),因为数组名就是该数组的首地址,也是数组第一个元素的地址。

    此时可以认为指针ptr就是数组str(反之不成立),ptr为指向数组第一个元素的指针,值得注意的是:ptr是一个可以变化的指针变量,而str是一个常数,因为数组一经被说明,数组的地址也就是固定的,因此str是不能变化的这样原来对数组的处理都可以用指针来实现。如对数组元素的访问,既可以用下标变量访问,也可以用指针访问。

    以下代码的打印结果一样

    int *pa,a[]={3,4,5,6,7,3,7,4,4,6};
    for (int i=0;i<=9;i++)
    {
    printf ( “%d”, a[i] );

    printf ( “%d”,  *(a+i) );

    printf(“%d”, pa[i] );

    printf ( “%d”, *(pa+i) );

    }

     指针变量也可以指向多维数组,例如,在一个三维数组中,引用元素c[i][j][k]的地址计算最终将换成:*(*(*(c+i)+j)+k)。

      若有如下说明:

      int a[3][4];

      int *p;

      p=a;

      p是指向整型变量的指针;p=a使p指向整型二维数组a的首地址。*(*(p+1)+2)表示取a[1][2]的内容;*p表示取a[0][0]的内容,因为p是指向整型变量的指针;p++表示p的内容加1,即p中存放的地址增加一个整型量的字节数2从而使p指向下一个整型量a[0][1]。公式:a[j][k]等价于*(a+(j* row_length)+k)

     

    三、指针常量:

    int const * pi与int * const pi

    int * const pi是将指针pi被定义为常量指针,

    int const *pi == const int *pi是将指针pi所指的内容定义为常量

    注意看如下代码:

    int i1=30;
    int i2=40;

    int * const pi=&i1;

    pi=&i2;    //4.注意这里,代码不能编译成功,因为上一句指针pi被定义为了常量,不能再对pi赋值
    再看下面代码:

    int i1=30;

    int i2=40;

    int  const *pi=&i1;

    pi=&i2;  //注意这里,pi可以在任意时候重新赋值一个新内存地址

    i2=80;    //5.想想看:这里能用*pi=80;来代替吗?当然不能
    printf( “%d”, *pi ) ;  //6. 输出是80,但是不能通过*pi来改变i2了

    补充:const int * const pi=&i;// pi值不能改,也不能通过pi修改i的值。因为不管是*pi还 是pi都是const的

    此处有总结:

    1) 如果const 修饰在*pi前则不能改的是*pi(即不能 类似这样:*pi=50;赋值)而不是指pi.

    2) 如果const 是直接写在pi前则pi不能改(即不能类似 这样:pi=&i;赋值)。

    四、值传递,地址传递,引用传递

    看下面三个题目

    1、值传递
    void Exchg1(int x, int y)
    {
    int tmp;
    tmp=x;
    x=y;
    y=tmp;
    printf (“x=%d,y=%d ”,x,y)
    }
    void main()
    {
    int a=4,b=6;
    Exchg1 (a,b) ;  //只是将a的值赋给x,b的值赋给y,并不能通过xy来改变ab的值
    printf(“a=%d,b=%d ”,a,b)
    }
    输出的结果 :
    x=6, y=4
    a=4, b=6
    2、地址传递
    Exchg2(int *px, int *py)
    {
    int tmp=*px;
    *px=*py;
    *py=tmp;
    print(“*px=%d,*py=%d ”,*px,*py);
    }
    main()
    {
    int a=4;
    int b=6;
    Exchg2( &a,&b);  //指针px,py的值已经分别是a,b变量的地址值了。接下来,对*px,*py的操作当然也就是对a,b变量本身的操作
    Print (“a=%d,b=%d ”, a, b);
    }
    *px=6, *py=4
    a=6, b=4
    3、引用传递
    Exchg3(int &x, int &y)  //注意定义
    {
    int tmp=x;
    x=y;
    y=tmp;
    print(“x=%d,y=%d ”,x,y);
    }
    main()
    {
    int a=4;
    int b=6;
    Exchg3(a,b);  //Exchg3时函数会将a,b 分别代替了x,y了,我们称x,y分别引用了a,b变量
    Print(“a=%d,b=%d ”, a, b);
    }
    x=6, y=4
    a=6, b=2

     

    最后对值传递与引用传递作一个比较:

     

    1. 在函数定义格式上有不同:
    值传递在定义处是:Exchg1(int x, int y);
    引用传递在这义处是:Exchg1(int &x, int &y);

     

    2. 调用时有相同的格式:
    值传递:Exchg1(a,b);
    引用传递:Exchg3(a,b);

     

    3. 功能上是不同的:
    值传递的函数里操作的不是a,b变量本身,只是将a,b值赋给了x,y函数里操作的只是x,y变量而不是a,b,显示a,b的值不会被Exchg1函数所修改。
    引用传递Exchg3(a,b)函数里是用a,b分别代替了x,y。函数里操作的是a,b。

     

  • 相关阅读:
    Large repunit factors (Project Euler 132)
    有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767
    ZJU 17th 校赛
    2015-2016ACM-ICPC NEER northern-subregional-contest C Concatenation
    BestCoder Round #93 ABC
    Codeforces Round #404 (Div. 2) DE
    Fibonacci数列的幂和 zoj 3774
    bitset在acm中的应用
    Codeforces Round #398 (Div. 2) BCD
    Hook length formula 学习笔记 UVALive 6625
  • 原文地址:https://www.cnblogs.com/leeplogs/p/5866565.html
Copyright © 2011-2022 走看看