C语言--指针

指针在C语言中的地位很高。记得上大学那会,不是能够很好的理解指针这个东西,经常一节课下来听懂的并没有多少,当然,主要原因是没好好听课尴尬。这几年中对于编程语言的理解更加的进步,渐渐的,也就能够明白原来指针是这样的。

指针---就是内存地址。也是一个变量,只是这个变量中保存的数据是其他变量的地址而已。这里说了指针也是一个变量,那么指针的声明应该是和变量的声明一样喽。是的,但也有一点不一样。

变量的声明是:type var_name;

指针的声明是:type *var_name;

type代表变量的数据类型,var_name是变量名,才从上面的对比中可以发现,指针在声明时,在变量名之前加了一个 * ,这个可以算是指针的标识了。

关于指针变量的类型,必须是有效的C语言数据类型。这个类型指的是指针这个变量所指向的变量的类型。这句话的意思是,无论你声明一个int类型的指针还是声明一个char类型的指针,指针对象的类型是一样的,不同的是指针所指向的那个变量的类型一个是int类型,一个是char类型。下面,声明几个指针:

    int *ip;

    double *dp;

    float *fp;

    char *ch;

上面声明了4个指针变量,这4个指针变量的类型是相同的,但是指向的变量的类型不同。

下面,来看看指针的使用。上面我们说到了一个符号: *   下面我们在来说一个符号: &  。

在C语言中,每一个变量都有地址,每一个变量的内存地址,都可以使用&访问:

    int a = 10;

    printf("%x\n", &a);

打印结果:

5fbff7dc

Program ended with exit code: 0

这里就是使用 & 去变量a的地址。下面我们来使用 * 这个符号来定义一个指针,用来保存变量a的地址。

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

打印结果:

5fbff7f4

5fbff7f4

Program ended with exit code: 0

通过上面的结果我们可以看到,两个打印结果相同,这里就证实了,指针就是变量的内存地址。

上面代码中:ip = &a;是给指针变量赋值的语句,是将变量a的内存地址赋值给指针变量ip。在实际的开发中,有时我在定义指针的时候,并不能知晓要赋何值给这个指针,那么给指针变量赋一个NULL是一个很好的习惯,这样的指针是一个空指针。空指针是一个定义在标准库中的值为0的常量。

指针的声明和定义已经说了,下面来说下指针相关的操作和使用:

1、指针的运算。

指针的运算分为算术运算和逻辑运算,算术运算的符号有:++,--,+,-。逻辑运算符号有:==,<,>,<=,>=。下面逐个说明。

还用上面我们声明的指针ip,在上面ip的打印结果是5fbff7f4

我们在代码中加入 ip++; 再打印ip的结果,

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

    ip++;

    printf("%x\n", ip);

运行结果:

5fbff7f4

5fbff7f4

5fbff7f8

Program ended with exit code: 0

当我们对ip进行自增运算的时候,其结果比不是+1,而是+4,这是为何?

我们知道,指针是变量的内存地址,在上面的打印结果也证实了这一点。这样就很好理解了,我们知道,在内存管理中,int类型的数据在内存中占有4个字节的内存,所以,ip++就不是简单的+1,而是加了一个内存空间。ip++后,指向的是变量a的内存地址后面的那个地址了。同理,ip--也不是简单的-1而是-4。

我们在用代码来看看+,-运算:

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

    ip++;

    printf("%x\n", ip);

    ip -= 2;

    printf("%x\n", ip);

    ip += 1;

    printf("%x\n", ip);

打印结果:

5fbff7f4

5fbff7f4

5fbff7f8

5fbff7f0

5fbff7f4

Program ended with exit code: 0

从打印结果来看,ip+2,也不是直接+2,而是加了两个int类型的内存空间(也就是8个字节),ip-1也是减去了1个int类型的内存空间(4个字节)。

相对于算术运算,逻辑预算更简单,指针也是变量,所以指针的逻辑运算和其他变量的逻辑运算相同。这里就不多说了。



在指针的知识中,还有一个很重要的东西,指针数组。

在上一篇文章中,已经对数组的知识进行了简单整理,知道了数组的用途很广泛。可能有一种情况,我们想让数组存储的不是直接的变量,而是指向变量的指针,这就要用到指针数组。下面我们来看一个示例:

声明一个指向int类型的指针数组:

    int a[3] = {10,20,30};

    int *array[3];

    for (int i = 0; i < 3; i++) {

        array[i] = &a[i];

    }

    for (int j = 0; j < 3; j++) {

        printf("a[%d]的地址:%x, 值:%d\n", j, array[j], *array[j]);

    }

打印结果:

a[0]的地址:5fbff7fc, 值:10

a[1]的地址:5fbff800, 值:20

a[2]的地址:5fbff804, 值:30

Program ended with exit code: 0

从代码和结果来看,array数组就是一个指针数组,存储了数组a中变量的内存地址。



下面,再来说说指向指针的指针-----二级指针。

指针中存在多级指针的概念,二级指针是最简单的多级指针。先来看一张图:


通过上面的图,很容易发现二级指针,其实就是指向变量内存地址的指针。就如同上面图里的那样,变量a是一个整型变量,值为100,定义一个指针p指向a,那么,p中保存的值就是a的内存地址,再用一个指针q指向指针p,q中保存的就是指针p的内存地址。这就是二级指针。

声明二级指针要用两个符号 * ,下面是一段二级指针的代码:

    int a = 100;

    int *p = &a;

    int **q = &p;

    

    printf("a = %d,p = %x,q = %x\n", a, p, q);

    printf("a = %d\n", *p);

    printf("a = %d\n", **q);

    

    printf("p = %x\n", &a);

    printf("p = %x\n", *q);

    

    printf("q = %x\n", &p);

打印结果:

a = 100,p = 5fbff7fc,q = 5fbff7f0

a = 100

a = 100

p = 5fbff7fc

p = 5fbff7fc

q = 5fbff7f0

Program ended with exit code: 0

通过上面的代码和打印结果,很明显就可以看出二级指针,指针,变量三者之间的联系。这里要注意一点不能使用&&a的方式来获取a变量的二级指针。


还有一点关于指针的使用时将指针作为函数的参数,或者作为函数的返回值。指针也是变量,这样的话,作为函数的参数就很好理解了,只是在函数定义的时候,将形参定义为指针即可。我们说的main函数就有一个指针数组作为形参。还有将指针作为函数的返回值,这个需要在函数声明时,返回值类型是指针,如:int *getMax();这样就可以返回一个指针了。另外需要注意一点,C语言中不允许,在函数外返回局部变量的地址,想要返回局部变量,可将局部变量修饰我static变量。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值