第6章 指针

尽管一个字包含了4个字节,它仍然只有一个地址。至于它的地址是它最左边那个字节的位置还是最右边那个字节的位置,不同的机器有不同的规定。
通过一个指针访问它所指向的地址的过程称为间接访问或解引用指针,这个用于执行间接访问的操作符是单目操作符*。
在你对指针进行间接访问之前,必须非常小心,确保它们已被初始化。

C标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,你可以给它赋一个零值。为了测试一个指针变量是否为NULL,你可以将它与零值进行比较。NULL指针的概念非常有用,因为它给了你一种方法,表示某个特定的指针目前并未指向任何东西。例如,一个用于在某个数组中查找某个特定值的函数可能返回一个指向查找到的数组元素的指针。如果该数组不包含指定条件的值,函数就返回一个NULL指针。(尽管这个技巧在C程序中极为常用,但它违背了软件工程的原则。一种更为安全的策略是让函数返回两个独立的值:首先是个状态值,用于提示查找是否成功;其次是个指针,当状态值提示查找成功时,它所指向的就是查找到的元素。)
对一个NULL指针进行解引用操作是非法的。
除了NULL指针之外,再也没有任何内建的记法来表示指针常量。在极少见的情况下,我们偶尔需要使用指针常量,这时我们可以通过把一个整型值强制转换为指针类型来创建它。
对所有的指针变量进行显式的初始化是种好的做法。初始化的方法有:(1)使它指向现有的内存;(2)给它分配动态内存。
如果你已经知道指针将被初始化为什么地址,就把它初始化为该地址,否则就把它初始化为NULL。例如:

int a;
int *d = &a;

指针的指针,例如:

int a = 12;
int *b = &a;
int **c = &b;

*cp++,优先级表格显示后缀++操作符的优先级高于*操作符,但表达式的结果看上去像是先执行间接访问操作。事实上,这里涉及3个步骤:(1)++操作符产生cp的一份拷贝,(2)然后++操作符增加cp的值,(3)最后在cp的拷贝上执行间接访问操作。这个表达式常常在循环中出现,首先用一个数组的地址初始化指针,然后使用这种表达式就可以访问该数组的内容了。例如:

// 计算一个字符串的长度
size_t strlen(char *string)
{
	int length = 0;
	while(*string++ != '\0')
	{
		length++;
	}
	return length;
}

**指针加上一个整数的结果是另一个指针。当一个指针和一个整数量执行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整。如果p是一个指向char的指针,则表达式p+1就指向下一个char。如果p是个指向float的指针,那么p+1就指向下一个float,其他类型也是如此。**例如,在某台机器上float占据4个字节,在计算float型指针加3的表达式时,这个3将根据float类型的大小(此例中为4)进行调整(相乘),这样实际加到指针上的整型值为12。

C的指针运算只限于两种形式:
(1)指针±整数,标准定义这种形式只能用于指向数组中某个元素的指针。(让指针指向数组最后一个元素后面的那个位置是合法的,按对这个指针执行间接访问可能会失败。)例如:

#define N_VALUES 5
float values[N_VALUES];
float *vp;
for (vp=&values[0]; vp<&values[N_VALUES];)
{
	*vp++ = 0;
}

(2)指针-指针,只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果的类型是ptrdiff_t,它是一种有符号整数类型。
实际上,绝大多数编译器都不会检查指针表达式的结果是否位于合法的边界之内。当你使用指针运算是,必须非常小心,确保运算的结果将指向有意义的东西。
对指针执行关系运算也是有限制的,用下列关系操作符对两个指针进行比较是可能的:<,<=,>,>=,不过前提是它们都指向同一个数组中的元素。
标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第1个元素之前的那个内存位置的指针进行比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值