c语言指针总结(自用复习)

 

目录

1.指针变量

1.1地址

1.2指针的偏移

1.3空指针与野指针

1.4指针与元素值

2.指针与数组

2.1指针与一维数组

2.1.1指针指向数组方式与输出方式

2.1.2指针在数组中的偏移

2.2指针与二维数组a[M][N]

2.2.1 *p

2.2.2 (*q)[N]

2.3数组指针与指针数组

3.指针与函数

3.1指针类型的函数变量

3.2函数指针

4.指针与字符串

4.1字符串

4.2指针在字符串中的运用

4.3二种定义多个字符串的方法


1.指针变量

数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。

1.1地址

#include <stdio.h>

int main()
{
    int a=10;//定义int型变量a并赋值为10;
    int *p;//定义int型指针 p;

    p=&a;//指针指向 a;

    printf("%d\n",a);//变量a的值;
    printf("%d\n",*p);//解地址p取得的既定内存中的值(变量a的值);
    printf("%p\n",&a);//变量a在内存中的地址;
    printf("%p\n",p);//指针p所指的对象(即变量a)在内存中的地址;
    printf("%p\n",&p);//指针p自身在内存中的地址;
    return 0;
}

指针变量与其所指的变量间类型必须匹配,例如char类型的指针对应char类型的变量

定义取值时,需要加上 * (指针运算符),* 与 &同时使用时会相互抵消

指针自身的地址与指针所指对象的地址在内存中是两个不同的地址。

1.2指针的偏移

#include <stdio.h>

int main()
{
    int a=10;//定义int型变量a并赋值为10;
    int *p;//定义int型指针 p;

    p=&a;//指针指向 a;

    printf("%p\n",&a+1);//变量a偏移1个元素位置后在内存中的地址;
    printf("%p\n",p+1);//指针p所指的对象(即变量a)偏移1个元素位置后在内存中的地址;
    return 0;
}

当变量a是int 型时,偏移一个元素位置即4个字节(char型为1个字节),即与变量类型相同。

变量a在内存中的地址是常量(指针p的地址同样为常量,所以当指针偏移一个位置,使用 *p 则无法输出变量a。指针的地址的大小与编译器的位数有关,32位编译器指针地址为4字节,64位为8字节。

1.3空指针与野指针

无论是空指针还是野指针,都是错误的。

#include <stdio.h>

int main()
{
    int a=10;//定义int型变量a并赋值为10;
    int *p;//定义int型指针 p;

    int *q=NULL; //空指针;

    *p=20;//指针未指向既定内存,野指针;
    *q=20;//空指针,无法访问;

    return 0;
}

1.4指针与元素值

通过指针改变元素值有两个方法,一是通过解地址符号即*p直接改变元素的值;

#include <stdio.h>

int main()
{
    int  a=15,b=99,c=222;//定义三个int型变量a,b,c;
    int  *p=&a;//定义指针p(定义需要加上 * ),并指向变量a;

    *p=b; //解地址p(即*p=变量a),可得a=b,所以a=99;

    c=*p; //同理 c=a,c=99;

    printf("%d %d %d %d\n",*p,a,b,c);//输出*p=99,a=99,b=99,c=99;
    return 0;
}

 二是通过改变指针所指向的元素来改变解地址后的值(并非元素的本值)。

#include <stdio.h>

int main()
{
    int  a=15,b=99;//定义变量a,b并分别赋值15和99;
    int  *p=&a,*q=&b;定义指针p指向a,定义指针q指向b;

    printf("%d\n",*p);//*p=a,所以值为15;
    printf("%d\n",a);//值为15;
    printf("%d\n",*q);//*q=b,所以值为99;
    printf("%d\n",b);//值为99;

    p=q;//将指针q所指向的地址赋值给指针p,此时指针p指向变量b而非变量a;

    printf("%d\n",*p);//指针p指向变量b,所以*p=b=99;
    return 0;
}

2.指针与数组

2.1指针与一维数组

2.1.1指针指向数组方式与输出方式

两种指向方式,一种完整形式,另一种是简化形式;

三种输出方式(除了以非指针方式a[0]外),分别为解地址p、p[N]、解地址a;

#include <stdio.h>

int main()
{
    int a[5]={1,2,3,4,5};
    int *p;
    
    p=&a[0];//完整形式的指针与数组指向关系,指向数组a的首元素地址;
    p=a;    //简化形式,同样指向数组a的首元素地址;

    printf("%d",*p); //解地址p方式输出a[0],首元素地址;输出1;
    printf("%d",p[1]);//输出第二个元素;输出2;
    printf("%d",*a);//解地址a方式输出,数组a[N]中,a就是数组的首元素地址;输出1;
    
    return 0;
}

2.1.2指针在数组中的偏移

如果指针变量 p 已指向数组中的一个元素,则 p+1 指向同一数组中的下一个元素,p-1 指向同一数组中的上一个元素。

#include <stdio.h>

int main()
{
    int a[5]={1,2,3,4,5};
    int *p;
    
    p=a;    //简化形式,同样指向数组a的首元素地址;

    printf("%d\n",a[1]);//数组方式输出第二个元素;

    //此三种方法都使用了指针的偏移;
    printf("%d\n",*a+1);//数组首元素地址+1,输出第二个元素;
             //此方法中 a 与指针用法类似,但是a不是指针,因为a不是变量,是常量,所以a不能被修改;
             //a++在这里不能使用,会报error;
    printf("%d\n",*(p+1));//指针+1方式输出第二个元素;

    printf("%d\n",p[1]);//指针[1]方式输出第二个元素;

    
    return 0;
}

2.2指针与二维数组a[M][N]

2.2.1 *p

定义:

*p(定义单个元素的指针)在二维数组中有三种方式与二维数组产生指向关系

        p=&a[0][0]  是完整指向形式,指向首地址为a的二维数组的第0行第0列,指向1;

        p=a[0] 是简化形式,指向首地址为a的二维数组的第0行,也就是将二维数组的行内元素看作一个整体,指向首元素 1;

        p=*a 是简化形式,指向首地址为a的二维数组的第0行,同上;

输出:

printf("*p=%d\n",*p);  //输出1;

printf("p[1]=%d\n",p[1]); //前面定义p指针指向第0行,这里p[1]指第0行第1个,即输出2;

2.2.2 (*q)[N]

(*q)[3](定义容量为3的一维数组行指针)在二维数组中有两种方式与二维数组产生指向关系

        q=&a[0] 是完整指向形式,使指针q指向二维数组的第0行,如果使用此方法进行指向,输出时则根据这里指向的行数进行输出;例如q=&a[1],则指向数组第1行 ,输出q[1][1],则输出指向的那一行后面的2行(指针指向的行数在输出时记为0),具体看下例;

        如有数组a[3][3],即三行三列,定义指针 *p=&a[1],指向数组第1行首元素,输出p[2][1]时就会超出数组内存范围,因为定义数组指向第1行元素地址,第0行不在此范围,所以只能输出原数组的第1行和第2行,输出第2行第2个元素时应表达为p[1][1]。

        q=a  是简化形式,指向二维数组的第0行地址;

输出 

printf("*(*(q+0)+0)=%d\n",*(*(q+0)+0));   //(指向0行时)输出二维数组的第0行第0个元素

printf("*(q[2]+1)=%d\n",*(q[2]+1));  //(指向0行时)输出二维数组的第2行第1个元素

printf("q[2][2]=%d\n",q[2][2]);    //(指向0行时)输出二维数组的第2行第2个元素

#include <stdio.h>
#define M 3
#define N 3
int main()
{
    int a[M][N]={
		{1,2,3},
		{4,5,6},
		{7,8,9},
    };
    int *p;//单个元素指针
    p=&a[0][0];    //完整表达形式;
    p=a[0];        //a[0]代表数组起始元素地址;
    p=*a;          //*a代表数组起始元素地址;

    printf("*p=%d\n",*p); //输出1;
    printf("p[1]=%d\n",p[1]);//前面定义p指针指向第0行,这里p[1]指第0行第1个,即输出2;
    printf("\n\n");

    int (*q)[3];//定义容量为3的一维数组的行指针;
    q=a;      //指向二维数组的第0行地址;
    q=&a[0];  //完整表达式,使指针q指向二维数组的第0行;
		    //如果使用第二种方法进行指向,输出时则根据具体的行数进行输出;

    printf("*(*(q+0)+0)=%d\n",*(*(q+0)+0));//输出二维数组的第0行第0个元素,输出1;
    printf("*(q[2]+1)=%d\n",*(q[2]+1));//输出二维数组的第2行第1个元素,输出8;
    printf("q[2][2]=%d\n",q[2][2]);//输出二维数组的第2行第2个元素,输出9;
    
    return 0;
}

 输出结果为:​

 

2.3数组指针与指针数组

数组指针是指向数组的指针,它还是一个指针,只不过指向数组而已,2.1和2.2所说的指针就是数组指针。

指针数组实际是一个数组,长度是由数组本身决定,这个数组的所有元素都是指针类型,存放的都是地址。指针数组是一个由指针变量组成的数组,也就是说其中的元素都是指针变量。

#include <stdio.h>
#define M 3
int main()
{
    int a[M]={10,20,30}; //定义一个一维数组;
    int *p[M];   //定义一个指针数组;
    for(int i=0;i<M;i++){
        p[i]=&a[i];    //使用for循环将指针数组中的每个指针变量分别指向下标相同的一维数组;
    }
    for(int i=0;i<M;i++){
        printf("a[%d]:%d\n",i,*p[i]); //通过指针数组输出一维数组中的元素;
    }

    return 0;
}

 输出结果:

3.指针与函数

3.1指针类型的函数变量

函数的参数可以是单个int 、char变量、数组名(数组首元素地址),也可以是指针变量。

函数的参数遵循实参与虚参相统一原则:参数个数一致且变量类型一致;

#include <stdio.h>


void x(int *p1,int *p2,int *p3){
    void y(int *p1,int *p2);
    if(*p1<*p2){
		y(p1,p2);
    }
    if(*p2<*p3){
		y(p2,p3);
    }
    if(*p1<*p3){
		y(p1,p3);
    }
}
void y(int *p1,int *p2){
    int z;
    z=*p1;
    *p1=*p2;
    *p2=z;
}

int main()
{
    int a,b,c;
    int *p1,*p2,*p3;
    scanf("%d%d%d",&a,&b,&c);
    p1=&a;
    p2=&b;
    p3=&c;
    x(&a,&b,&c);
    printf("%d>%d>%d\n",*p1,*p2,*p3);
    return 0;
}

 

3.2函数指针

函数同样可以作为指针来使用:

定义指针后应注意将指针的地址指向函数的地址,才能实现对应关系。

声明格式:数据类型(*函数名)(参数)         例如   int(*p)(int)

# include <stdio.h>

int Max(int, int);  //函数声明

int main(void)
{
    int(*p)(int,int);  //定义一个函数指针
    int a,b,c;
    p=Max;  //把函数Max赋给指针变量p, 使p指向Max函数

    printf("please enter a and b:");
    scanf("%d%d",&a,&b);

    c=(*p)(a,b);  //通过函数指针调用Max函数

    printf("a=%d b=%d max=%d\n",a,b,c);
    return 0;
}
int Max(int x,int y){  //定义Max函数

    int z;
    if (x>y){
        z=x;
    }else{
        z=y;
    }
    return z;
}

 输出结果:

 

4.指针与字符串

4.1字符串

#include <stdio.h>

int main()
{
    char str[10]="ABCD";
    printf("%s\n",str);//str为字符串首地址,输出ABCD;
    printf("%s\n",str[2]);从C开始输出,输出CD;
    return 0;
}

4.2指针在字符串中的运用

 

#include <stdio.h>

int main(void)
{  
    char *a="abc";  

    printf("输出字符:%c \n",*a);    //输出字符,使用"%c"
    printf("输出字符:%c \n",*(a+1));  //输出字符,使用"%c"
    printf("输出字符串:%s \n",a);   //输出字符串,使用"%s";而且a之前不能有星号"*"
    
}

输出结果:

 

4.3二种定义多个字符串的方法

#include <stdio.h>

int main()
{
    char a[3][10]={"aaa","bbb","ccc"};
    char *b[3]={"ddd","eee","fff"};

    for(int i=0;i<3;i++){   //二维字符串数组的存储方式
        printf("   a[%d]=%s\n",i,a[i]);
        printf("所占地址:%p\n",a[i]);
    }
    for(int i=0;i<3;i++){   //一维指针数组的存储方式
        printf("   b[%d]=%s\n",i,b[i]);
        printf("所占地址:%p\n",b[i]);
    }
}

输出结果:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值