指针与数组
数组名所代表的就是该数组最开始的一个元素的地址,在计算数组元素a[i]的值时,C语言实际上线将其转换为 (a+i)的形式,然后再进行求值。他们是等价的,可以将指针后面加下标,比如pa[i]和 (pa+i)是等价的,但是指针比单纯的数组名要快一些。
有一点很重要的,数组名和指针之间有一个不同之处,指针是一个变量,因此,pa+a和pa++都his合法的,但数组名不是变量(类似一个宏定义?用数组名替换地址?),所以进行对自身的增减运算是非法的。
有时如果将数组名传递给函数,函数可以根据情况判定是按照数组处理还是按照指针处理,随后根据相应的方式操作该函数,为了更直观的表示数组名和指针,可以同时使用两种表示方法。
也可以将数组的一部分传递给函数,不必须从起始位置运算、对于函数来说,它并不关心所引用的是否是一个大数组的其中一部分。
地址算数运算
*allocp = allocbuf起始是存储空间的起始位置。
之后的函数中allocbuf + ALLOCSIZE是存储空间的最后的地址,因为存储空间不一定是从0开始,所以起始地址加上总大小得到的就是这个存储空间最后的地址。减去allocp是将已分配的空间减去,得到的必然是小于或等于空间大小的数,这个数就是剩余的空间的大小。
这就比如从30000开始之后10000的部分是存储空间,已分配空间在35000那么30000加10000减去35000就是剩余的空间了。
之后的那个allocp自增让我懵了一下。自增之后为啥又减了,仔细看发现。allocp += n确实是自增了,本身的地址也改变了。但是allocp - n只是将数值传回了,并没有对自己赋值。
这个函数确实不完善,afree函数很简单就是确定参数的地址是否在存储空间内。是的话就将已分配的地址变成新的地址。
指针也可以初始化,对指针有意义的初始化只能是0或者是表示地址的表达式,表达式代表的地址必须是已经定义的具有适当类型的数据的地址。
static char *allocp = allocbuf;
allocbuf需要在之前已经定义为字符数组才是有意义的。
C语言保证0永远不是有效的数据地址。因此,返回值0可用来表示发生了异常事件。
指针与整数之间不能相互转换,但0是唯一的例外,常熟0可以赋值给指针,指针也可以和常量0进行比较。程序中通常用符号常量NULL代替常量0。符号常量0定义在标准头文件<stddef.h>中。
在某些情况下对指针可以进行比较运算。如果指针p和q是同一个数组的成员,那么他们之间就可以进行类似于==、!=、<,>=的关系比较运算。任何指针与0进行相等或不等的比较运算都有意义。但是指向不同数组的元素的指针之间的算数或比较运算没有定义,(这里有一个特例。指针的算数运算中可使用数组最后一个元素的下一个元素的地址。)
指针可以和整数进行相加或相减运算。无论指针对象是何种类型都成立,相加的整数会根据指针指向的类型长度按比例缩放,
指针相减也是有意义的,同数组中的指针相减会得到指针之间字符的数量。
指针的算数运算具有一致性,所有的指针运算都会自动考虑它所指向的对象的长度。
有效的指针运算包括相同类型指针之间的赋值运算;指针同整数之间的加法或减法运算;指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为0或指针与0之间的比较运算。除此之外其他所有的指针运算都是非法的。(两个指针之一是void *类型的情况除外)