C语言指针通览

指针是对内存中对象的引用(通常实现为机器地址)。它是C语言提供的一种间接操纵数据的方法(通常C语言通过提供基本数据类型(int,float,char)或构建复合数据类型(struct)直接操纵数据)。

基本用法如下:

  • 通过“已有类型+*a”的方式将变量a声明为一个指向某类型的指针(机器地址)。
    • e.g. int *a 即声明了变量a是指向int类型的指针,注意a是指针,不是它指向的int类型变量!
    • 此外这里的已有类型指的是基本数据类型(int,float,char)或构建的复合数据类型(struct)
  • 在声明之后,我们可以使用*a完成对这个类型值的引用。int *a之后的语句,*a的含义就成了这个被指向的int变量自身。特别的,当a指向的是数组时,*a则表示a[0]。
  • 一元操作符&表示取一个对象的机器地址。e.g. *&b与b是完全相同的(此处的b指的是某类型变量而非指针)

指针的意义:间接操纵

  • 为什么要间接操纵而不直接操纵呢?
    • 因为在C语言中,所有函数参数采用按值传递,也就是说,如果函数向参数变量赋一个新的值,该赋值作用只局限于函数内部,在函数中直接操纵并不能在函数外真正改变变量的值。
    • 出了这个函数,变量如果想要得到改变,还得写一个专门的return语句使变量得到已经变化的值。但是若有多个变量值进行了改变,那么return不过来了怎么办呢,那么就在函数中用指针间接操纵以达到改变变量值的目的。所以说这就是void函数没有返回值但是也能存在且非常合理地存在的一种底层逻辑。
    • 我们把想改变的变量的指针传进函数中,而某些作为常量(不想改变的变量)就传进该变量的“真身”。举个例子:

以下函数把笛卡尔坐标转换为极坐标:

               void polar(float x, float y, float *r, float *theta)//此处传入的就是想改变的变量的地址和作为常量传入的x、y的真身

                 {

                     *r = sqrt(x*x+y*y);

                     *theta = atan2(y,x);

                     }

        值得注意的是,函数的参数列表里声明了指针r和theta分别指向一个浮点类型变量,而这个浮点类型的变量名不一定真叫r和theta(一般还真叫r和theta,为了清晰明确地暗示传入的该是哪个变量的地址),传入的仅仅只是地址。

        真叫r和theta完全没问题,因为在主函数中的r和theta是浮点变量,而在polar函数列表中的是指向他俩的指针(地址),函数列表中的变量名任意取,与主函数中的变量重名也无所谓,看的主要是真正传入的东西。

        所以在定义函数之后,主函数中调用该函数时,是这样的:

                          polar(x,y,&r,&theta);//这指的就是将主函数中r和theta的地址传入

        如果你在主函数中把极坐标r和theta声明成别的名字,叫做r1,theta1,那么调用函数的指令可以变成:

                           polar(x,y,&r1,&theta1)


 

  • 指针的其他妙用(动态分配内存空间,malloc函数)
    • 使用stdlib.h中的malloc函数和sizeof算子为数组或其他数据结构预留恰当的内存空间,并返回一个指向该内存空间的指针。
    • 这意味着可以动态改变数组的长度:从命令行获取数组长度N,应用malloc函数和sizeof算子进行内存的申报。示例如下:

#include <stdlib.h>

main (int argc, char *argv[] )//表示从命令行获取信息,argc表示加上调用的指令名之后的变量个数,argv[]是指针数组,每个元素指针指向以char的类型储存调用的指令名(argv[0])和其他输入,在此处“其他输入”是N,此处传入的是指向指针数组argv[]的地址

        { long int N = atol (argv[1]);//atol函数的参数列表中传入的就是指针

           int *a = malloc(N*sizeof (int));

          ......

           }

值得注意的是,如果在大型程序中想节省空间,可以对应malloc函数匹配一个free()函数释放该内存块。


  • 指针的指针
    • 类型*+*变量名,指的是,该变量是指针,指向类型为“类型*”的变量,而类型*的变量又指向类型为“类型”的变量。
      • e.g. int* *a
    • 该类表示方式主要用于表示指针数组在函数中传参。
      • e.g. function(int *a[])相当于function(int* *a)(指针数组的指针被传入,即第一个指针元素的地址)
      • e.g. function(int a[])([]中可填可不填数字,但是二维数组的第二个[]一定要填)相当于function(int *a)(传入数组时)

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值