语法-指针

概念:内存是以字节为单位的一片连续的存储空间,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\n",p);%p是以十六进制输出指针的地址。

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

如果指针变量p指向一个普通变量a,此时又不想指向a了,可以用这几种语句让p还原为初始状态(没有指向任何变量),p=NULL;或者p=0;或者p='\0';这里的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\n",a,b);
    swap1(&a,&b);///取址
    printf("a=%d,b=%d\n",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\n",*pp);
    printf("**pp=%d\n",**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\n",p);
    printf("*p=%d\n",*p);
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<2;j++)
        {
            printf("1: (p+%d)+%d = %d \n",i,j,*(a+i)+j);
            printf("2: a[%d]+%d  = %d \n",i,j,a[i]+j);
            printf("3: *(a[%d]+%d)  = %d \n",i,j,*(a[i]+j));            ///行数组用下标法
            printf("4: *( *(a+%d)+%d ) = %d \n",i,j,*( *(a+i)+j ) );    ///指针表示法
            printf("5: ( *(a+%d) )[%d] = %d \n",(* (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\n",a);
    p[0]=&c;
    printf("p[0]=%d, *p=%d, **p=%d\n",p[0],*p,**p);
    for(i=0;i<5;i++)
    {
        p[i]=a+i;
        printf("*a=%d, *p=%d, p[%d]=%d, **p=%d\n\n",*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不怎么用指针,略知一二即可。

 

 

 

 

posted @ 2018-11-11 12:16  守林鸟  阅读(435)  评论(0编辑  收藏  举报