pointer - yaokun123/php-wiki GitHub Wiki

指针

一、指针

1.几个概念

  • 指针

指针就是一个地址

  • 指针变量

指针变量是用来存放指针(一个地址)的变量

  • 指针变量与普通变量的区别

普通变量存放的是数据,指针变量存放的是地址

  • 指针变量的类型

存放的地址指向的数据的数据类型

2.取地址运算符和取值运算符(取值与取址)

如果需要获取某个变量的地址,可以使用取地址运算符(&)

如果需要访问指针变量指向的数据,可以使用取值运算符(*)

3.指针的声明和赋值

类型名 *指针变量名

#eg: char *pa;

#eg: int *pb;

  • 申明并赋值
#include<stdio.h>

int main(){
    char a = 'F';//这是声明一个普通变量,a存放的就是字符F

    char *pa = &a;//这是声明一个指针变量pa,并将a的地址存放在指针变量pa中
    //注意赋值时等号(=)的右边必须为一个地址
    //char *pa = a;//由于a不是一个地址,所以这种赋值是错误的

    printf("a的地址为:%p\n",&a);
    printf("pa的值为:%p\n",pa);
    return 0;
}
  • 申明后赋值
#include<stdio.h>

int main(){
    char a = 'F';//这是声明一个普通变量,a存放的就是字符F

    char *pa;//这里只声明了一个指针变量,还没赋值

    //错误初始化:*pa = &a;//因为指针变量pa已经声明,所以此处不该有*号,有*号意味着修改指针的值,要避免访问未初始化的指针
    //错误初始化:*pa = a;//因为指针变量pa已经声明,所以此处不该有*号,有*号意味着修改指针的值,要避免访问未初始化的指针

    pa = &a;//正确初始化,将a的地址赋值给指针变量pa

    return 0;
}
  • 避免访问未初始化的指针
int main(){
    int *a;//此处的指针没有被初始化
    *a = 123;//间接访问很危险
    return 0;
}

4.修改指针的值

#include <stdio.h>

int main(){
    //定义两个普通变量
    char a = 'F';
    int f = 123;

    //定义两个指针变量
    char *pa = &a;
    int *pb = &f;

    //打印指针变量指向的值
    printf("a = %c\n",*pa);//F
    printf("f = %d\n",*pb);//123

    //修改指针变量指向的值
    *pa = 'C';
    *pb += 1;

    //打印修改后的指针变量指向的值
    printf("now,a = %c\n",*pa);//C
    printf("now,f = %d\n",*pb);//124
    //打印修改后的变量的值
    printf("now,a = %c\n",a);//C
    printf("now,f = %d\n",f);//124

    //打印指针变量占用的内存空间
    printf("sizeof pa = %d\n",sizeof(pa));//8
    printf("sizeof pb = %d\n",sizeof(pb));//8

    //打印指针变量指向的地址
    printf("the addr of a = %p\n",pa);//0x7ffee6cb19ab(每次都不一样)
    printf("the addr of f = %p\n",pb);//0x7ffee6cb19a4(每次都不一样)
    return 0;
}

二、指针和数组

1.数组名其实是数组第一个元素的地址

#include <stdio.h>
int main(){
    char str[128];//定义一个字符数组
    printf("请输入域名:");//shuidi.cn
    
    scanf("%s",str);//数组名其实是数组第一个元素的地址,所以这里不用&符号
    printf("域名为:%s\n",str);//shuidi.cn
    //这个例子说明:
    //1、数组名其实是数组第一个元素的地址
    printf("str的地址是:%p\n",str);//0x7ffee3bfe920(每次都不一样)
    printf("str第一个元素的地址是:%p\n",&str[0]);/0x7ffee3bfe920(每次都不一样)

    return 0;
}

2.指针的运算

当指针指向数组元素的时候,我们可以对指针变量进行加减运算,这样做的意义相当于指向距离指针所在位置向前或向后第n个元素 对比标准的下表法访问数组元素,这种使用指针进行间接访问的方法叫做指针法

3.指针和数组的区别

数组名只是一个地址,而指针是一个左值

#include<stdio.h>
int main(){
    char str[] = "shuidi.cn";
    char *pa = str;
    int count = 0;
    //++的优先级高于*,所以此处是先将地址+1再取值
    while(*pa++ != '\0'){//此处不能直接使用str++,因为str是数组名字,不是左值;
        count++;
    }
    printf("一共有%d字符\n",count);
    return 0;
}

三、指针数组和数组指针

1.数组指针(指针)

数组指针是一个指针,它指向的是一个数组

定义:int (*pa)[5];//[]的优先级大于*,但是()的优先级与[]一样,但是结合是从左到右

#include<stdio.h>
int main(){
    int temp[5] = {1,2,3,4,5};
    int (*p1)[5] = &temp;
    int i;
    for(i=0;i<5;i++){
        printf("%d\n",*(*p1+i));
    }
    return 0;
}

2.指针数组(数组)

指针数组是一个数组,每个数组元素存放一个指针变量

定义:int pa[5];//[]的优先级大于

#include<stdio.h>
int main(){
    int a = 1;
    int b = 2;
    int c = 3;
    int d = 4;
    int e = 5;

    int *p1[5] = {&a,&b,&c,&d,&e};

    int i;
    for(i=0;i<5;i++){
        printf("%d\n",*p1[i]);
    }
    return 0;
}

int main(){
    char *p1[5] = {
        "aaaa",
        "bbbb",
        "cccc",
        "dddd",
        "eeee"
    };
    int i;
    for(i=0;i<5;i++){
        printf("%s\n",p1[i]);
    }
}

3.指向数组的指针

#include <stdio.h>
int main(){
    int temp[5] = {1,2,3,4,5};
    int *p = temp;

    int i;

    for(i=0;i<5;i++){
        printf("%d\n",*(p+i));
    }
}

四、指针和二维数组

c语言中并没有正真的二维数组,二维数组是通过线性扩展的方式实现

# include <stdio.h>
int main(){
    int a[2][3] = {{1,2,3},{4,5,6}};
    int i;
    int j;
    printf("二维数组a的地址:%p\n",a);
    printf("二维数组a[0]的地址:%p\n",a[0]);
    printf("二维数组a[0][0]的地址:%p\n",&a[0][0]);
    printf("*(a+1)=%d\n",**(a+1));//语法糖:*(a+1) = a[1]
    for(i=0;i<2;i++){
        for(j=0;j<3;j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

五、void指针和NULL指针

1.void指针

void指针我们把它称之为通用指针,就是可以指向任意数据类型的。也就是说,任何类型的指针都可以赋值给void指针

#include<stdio.h>
/**
将void类型的指针指向为其他类型的指针就需要强制转换
*/
int main(){
    int num = 1024;
    int *pa = &num;
    char *pb = "shuidi";
    void *pc;

    pc = pa;
    printf("pa:%p,pc:%p\n",pa,pc);
    printf("pa=%d,pc=%d\n",*pa,*(int *)pc);//注意强制转换

    pc = pb;
    printf("pb:%p,pc:%p\n",pb,pc);
    printf("pb=%s,pc=%s\n",pb,(char *)pc);

    return 0;
}

2.NULL指针

NULL代表该指针不指向任何东西

当你还不清楚要将指针初始化为什么地址时,请将它初始化为NULL;

在对指针进行解引用时,先检查该指针是否为NULL。

这种策略可以为你今后编写大型程序节省大量的调试时间。

#include <stdio.h>
int main(){
    int *pa;
    int *pb = NULL;

    printf("%d\n",*pa);
    printf("%d\n",*pb);
    return 0;
}

/**
NULL 不是 NUL(表示空字符'\0')
**/

六、指向指针的指针

#include <stdio.h>
int main(){
    int num = 520;
    int *p = &num;
    int **pp = &p;//pp就是指向指针的指针(pp里面存放的是指针的地址)


    printf("num:%d\n",num);
    printf("*p:%d\n",*p);
    printf("**pp:%d\n",**pp);

    printf("&p:%p,pp:%p\n",&p,pp);
    printf("&num:%p,p:%p,*pp:%p\n",&num,p,*pp);
    return 0;
}


int main(){
    //定义一个数组指针
    char *cBooks[] = {
        "《C程序设计语言》",
        "《C专家编程》",
        "《C和指针》",
        "《C陷阱与缺陷》",
        "《C Primer Plus》",
        "《带你学C带你飞》"
    };

    //定义一个指向指针的指针
    char **byFishC;

    //定义一个
    char **jiayuLoves[4];
    int i;

    byFishC = &cBooks[5];
    jiayuLoves[0] = &cBooks[0];
    jiayuLoves[1] = &cBooks[1];
    jiayuLoves[2] = &cBooks[2];
    jiayuLoves[3] = &cBooks[3];

    printf("FishC出版的图书有:%s\n",*byFishC);
    printf("小甲鱼喜欢的图书有:\n");

    for(i=0;i<4;i++){
        printf("%s\n",*jiayuLoves[i]);
    }
    return 0;
}


int main(){
    int array[10] = {0,1,2,3,4,5,6,7,8,9};
    int *p = array;
    int i;

    for(i=0;i<10;i++){
        printf("%d\n",*(p+i));
    }



    printf("-----------\n");
    int a[3][4] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };
    int m,n;
    for(m=0;m<3;m++){
        for(n=0;n<4;n++){
            printf("%d ",*(*(a+m)+n));
        }
        printf("\n");
    }
    int (*q)[4] = a;
    for(m=0;m<3;m++){
        for(n=0;n<4;n++){
            printf("%d ",*(*(q+m)+n));
        }
        printf("\n");
    }



    return 0;
}

七、指向常量的指针

#include <stdio.h>
//定义常量
#define PI 3.14


int main(){
    //还可以使用const关键字将一个变量变为常量
    int a = 1;
    const int b = 2;

    a = 2;//此时可以修改变量a
    printf("%d\n",a);

    //b = 1;//此时不能修改用const关键字定义的变量
    printf("%d\n",b);




    //指向常量的指针
    int num = 520;
    const int cnum = 880;
    const int *pc = &cnum;

    printf("cnum:%d,&cnum:%p\n",cnum,&cnum);
    printf("*pc:%d,pc:%p\n",*pc,pc);

    //*pc = 1024;//不允许
    pc = &num;//这个是可以的

    return 0;
}
⚠️ **GitHub.com Fallback** ⚠️