zoukankan      html  css  js  c++  java
  • 语法-指针

    概念:内存是以字节为单位的一片连续的存储空间,1k=1024字节,为了便于访问,给每个字节单元有一个唯一的编号,编号从0开始,第一字节单元编号为0,以后各单元按顺序连续编号,这些单元的编号叫做地址。

    1.数据类型有字节的差别,假设从0开始编号(一般不会从0开始编号的)。比如int 4个字节,int a=99;则表示0-3这片存储单元分给a,首地址是0;定义指针变量int *p;(在指针变量定义中,*是一个说明符,它表示其后的变量是指针变量,p是指针变量,而不是*p。也可以写成int* p,这样比较容易看清p为一个变量)。p=&a 表示p指向a的地址,此时p的值是0,但是p指向的范围是0-3四个字节,而不是单单0那个字节,取首地址。&为取址符,指针变量p存地址,要对变量a取地址,才能放进p里。所有指针变量的都是4个字节,存地址。取a的值的时候可以用*p表示(前提:p取a的地址。并且,此时的*是指针运算符,又称指向运算符,表示取指针变量所指的变量的值),*p和a的值都是99。并且当p指向a之后,修改*p,a的值也会改变,但是如果自增自减不能用*p++,需要用(*p)++。

    *和&的优先级一样,从右往左运算。p=&a。*p=a。&*p=p=*&p。

    printf("%p ",p);%p是以十六进制输出指针的地址。

    两个不同的指针可以指向同一个变量,并且指针之间可以相互赋值,两个指针变量都可以对所指对象进行修改。比如int p1,p2; p1=&a;p2=&a;等同于p1=&a;p2=p1;

    如果指针变量p指向一个普通变量a,此时又不想指向a了,可以用这几种语句让p还原为初始状态(没有指向任何变量),p=NULL;或者p=0;或者p='';这里的p并非指向0地址单元,而是一个确定的空值。(0是特殊的,如果用2000赋值给p,p=2000这样的语句是错误的)

    地址里存的值改变,变量才会改变,最典型的例子就是交换两个数的值。

    #include<stdio.h>
    using namespace std;
    void swap1(int* p1,int* p2)///指针变量类型决定传参需要取址
    {
        int temp=*p1;
        *p1=*p2;
        *p2=temp;
        return;
    }
    int main()
    {
        int a=1,b=50;
        printf("a=%d,b=%d
    ",a,b);
        swap1(&a,&b);///取址
        printf("a=%d,b=%d
    ",a,b);
        return 0;
    }

    继续定义变量double b=1.56;定义指针变量q指向b,double* q=b; double 8个字节,继3之后4-11这片存储单元分给b,首地址是4;q的存的地址值也是4。后续说明和int雷同。

    2.数组指针变量,注意数组不要越界

        int arr[100];       ///arr表示首地址地址
        int *p;
        p=arr;              ///可以写作p=&arr[0];
        p=p+1;              ///该表达式不是表示地址所在的字节+1,而是在数组里跳一个int类型的地址,即跳了4个字节
                   ///arr+i表示下标为i的元素的地址(如果从第0个算,表示第i个元素地址)

    3.多级指针

    int a=100;
        int* p;
        int** pp;
        p=&a;           ///指针也是数据类型,虽然存a的地址,但是自己也有地址
        pp=&p;          ///指针变量p的地址存到pp里,虽然pp也是指针变量,但是不能指向普通变量a,只能指向指针变量p
                        ///一级指针和二级指针不是相同的数据类型,不能相互赋值
        printf("*pp=%d
    ",*pp);
        printf("**pp=%d
    ",**pp);

    4.二维数组指针

    二维数组的存储空间也是连续的,只不过为了形象表示,一般分成很多行很多列。

      int a[3][2]={1,2,3,4,5,6};
        int *p;
        p=&a[0][0];             ///p取首地址,错误写法:p=a; 和 p=&a[0];
        printf("&a[0][0]=%d
    ",p);
        printf("*p=%d
    ",*p);
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<2;j++)
            {
                printf("1: (p+%d)+%d = %d 
    ",i,j,*(a+i)+j);
                printf("2: a[%d]+%d  = %d 
    ",i,j,a[i]+j);
                printf("3: *(a[%d]+%d)  = %d 
    ",i,j,*(a[i]+j));            ///行数组用下标法
                printf("4: *( *(a+%d)+%d ) = %d 
    ",i,j,*( *(a+i)+j ) );    ///指针表示法
                printf("5: ( *(a+%d) )[%d] = %d 
    ",(* (a+i) )[j] );        ///列用下标表示法
            }
        }

    5.数组作为函数参数

        int a[5];
        int b[3][4];
        int c[2][4][6];
        void print1( int a[] );
        void print2( int b[3][] );
        void print3( int c[2][4][]);

    6.指针数组

    int a[]={10,11,12,13,14};

    int *p[n];  ///[]优先级比*高,先形成一个p[n]数组,再定义成指针数组变量,它有n个指针类型的数组元素。

    错误赋值:p=a,因为p是个不可知的表示,只存在p[0]、p[1]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。

    *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值

    int main()
    {
        int i,a[]={10,11,12,13,14}, *p[5];
        int c=1005;
        printf("a=%d
    ",a);
        p[0]=&c;
        printf("p[0]=%d, *p=%d, **p=%d
    ",p[0],*p,**p);
        for(i=0;i<5;i++)
        {
            p[i]=a+i;
            printf("*a=%d, *p=%d, p[%d]=%d, **p=%d
    
    ",*a,*p,i,p[i],**p);
        }
        return 0;
    }
    /*
    a=6881000
    p[0]=6880976, *p=6880976, **p=1005
    *a=10, *p=6881000, p[0]=6881000, **p=10
    
    *a=10, *p=6881000, p[1]=6881004, **p=10
    
    *a=10, *p=6881000, p[2]=6881008, **p=10
    
    *a=10, *p=6881000, p[3]=6881012, **p=10
    
    *a=10, *p=6881000, p[4]=6881016, **p=10
    */

    都说指针是C语言的灵魂,但是acm不怎么用指针,略知一二即可。

     

     

  • 相关阅读:
    干货!常见的SQL面试题:经典50例!
    图解SQL基础知识,小白也能看懂的SQL文章!
    30多个Java实战项目,全部在这里了。
    Spring的@PropertySource注解使用
    20201226[java]两数相加
    1013.表-约束-唯一、主键、外键和排他
    1012.表-约束-检查
    1011.表-生成列
    1010.表默认值
    1009.表基础-初识表
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/9937408.html
Copyright © 2011-2022 走看看