指针与数组与函数指针

指针的本质分析

变量的本质是一段存储空间的别名,指针的本质是一种特殊类型的变量,这种变量的存储空间中存储的是另一个变量的地址。

*号的意义:
*号代表所申明的变量是指针;*号表示取指针所指向内存空间的值。

该使用传值调用还是传址调用:

当函数内部需要改变实参的值,则需要使用传址调用;

如果函数需要传入的参数类型复杂,体积巨大,又不希望参数在函数体内部被改变,应该使用const指针。

const指针:

const datatype* p;             	//p可以被改变,*p不能改变
datatype const* p;             	//p可以被改变,*p不能改变
datatype* const p;             	//p不可以改变,*p可以改变
const datatype* const p;    	//p和*p均不能改变

指针加法的运算规则:

指针与整数相加:p + n = (unsigned datatype)p + n * sizeof(datatype);

指针与指针相加:p + q = ((unsigned datatype)p + (unsigned datatype)q) / sizeof(datatype);

指针减法的运算规则:

指针与整数相加:p – n = (unsigned datatype)p + n * sizeof(datatype);

指针与指针相加:p – q = ((unsigned datatype)p – (unsigned datatype)q) / sizeof(datatype);

指针之间可以进行关系运算(<,<=,>,>=)。

指针之间可以进行比较运算(==,!=);

为什么需要多维指针?
指针的本质是变量,对指针也存在传值调用和传址调用的问题

数组的本质分析

数组是相同变量的有序集合。

数组的个数可以显式指定或隐式指定(即初始化时不说明数组大小)。

数组地址与数组名:

数组名代表数组首元素的地址;

数组的地址需要用取地址符&得到,数组首元素的地址与数组的地址值相同;

数组的地址与数组首元素的地址不是同一概念;

数组的地址包含起始地址与长度;

数组名可以看做指向数组第一个元素的常量指针。

指针以固定增量在数组中移动时,效率远高于下标访问

现代编译器的生成代码优化率已大大提高,在固定增量时,下标形式的效率已经和指针形式相当,考虑到代码可读性和维护的角度,更推荐使用下标形式。

数组的类型:
数组的类型由元素类型和数组大小共同决定。

例如:int array[5]的类型为int[5]。

利用typedef为数组类型重命名:typedef type(name)[size]

例如:typedef int(AINT5)[5]; AINT5 array;

定义数组指针:

type(*pointer)[size]

C语言中函数只会以值拷贝的方式传递参数,数组参数必然退化为指针,多维数组参数必须提供除第一维之外的所有维长度信息

用a[i]这样的形式对数组进行访问总是会被编译器解释为像*(a+i)这样的指针形式

数据会在什么时间退化成指针:

C语言标准规定,当数组名作为定义的标识符(也就是定义或声明数组时)、sizeof或&的操作数时表示数组本身,在其它的表达式中,数组名会被转换为指向第0个元素的指针。

函数与指针

C语言中的函数有自己特定的类型,函数的类型由返回值、参数类型和参数个数共同决定。

例如:int add(int i, int j)的类型为int(int, int);

一个函数总是占用一段连续的内存区域,函数名在表达式中可能被转换为该函数所在的内存区域的首地址。我们可以通过一个指针变量指向该地址从而实现对该函数的访问,这种指针就是函数指针。

函数指针的定义形式:returnType (*pointerName)(param list)

例如:int (*pointer)(int, int)定义了一个指向int(int, int)类型的函数指针pointer;

main函数

main函数一定是程序执行的第一个函数吗?

不一定,要看使用的编译器有没有相关的拓展。例如:gcc使用属性关键字后,可以在main函数之前之后执行函数

复杂指针的读取方式

C语言标准规定,对于一个符号的定义,编译器总是从它的名字开始读取,然后按照优先级顺序依次解析。

例如:int (* (*(*pfunc)(int *)) [5]) (int *)

先读取(pfunc),可以确定pfunc是一个指针,再读取((pfunc)(int)),可以确定pfunc是一个函数指针,参数类型为int*,返回值也是一个指针,接着读取(* ((pfunc)(int)) [5]),可以确定返回值指向了一个有5个元素的数组,数组的每一个元素也是一个指针,最后读取int ( (*(*pfunc)(int *)) [5])(int ),可以确定数组中的每一个指针元素指向了一个int(int)类型的函数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值