char ch = 'a';
char *cp = &ch;
让指针指向数组中的最后一个元素是合法的,但对它进行间接访问操作可能会失败。
ANSI C标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置进行比较。
1. *cp+1
*
操作符的优先级高于+
,所以首先执行间接访问操作。我们可以得到它的值,我们取得这个值的一份副本并把它与1相加,表达式的最终结果为’b’。
这个表达式的最终结果的存储位置并未清晰定义,所以它不是一个合法的左值。
2. ++a和a++
在操作数之前的操作符在变量被使用之前增加它的值;
在操作数之后的操作符在变量被使用之后增加它的值;
int a,b,c,d;
a = b = 10;
c = ++a; //a增加至11,c得到的值为11
d = b++; //b增加至11,d得到的值为10
++a的结果是a值的副本,并不是变量本身,因此无法向一个值进行赋值操作。
++a = 10; //非法
3. ++cp
表达式的结果是增值后的指针的一份拷贝,因为前缀++先增加它的操作数的值在返回这个结果。这份副本的存储位置并未清晰定义,所以它不是一个合法的左值。
4. cp++
后缀++操作符同样增加cp的值,但它先返回cp值的一份拷贝然后在增加cp的值。
5. *++cp
相当于:
*( ++cp )
它返回ch后面那个位置的值的结果,cp指向ch后面那个位置。
6. *cp++
相当于:
*( cp++ )
它返回一个字符a,cp指向ch后面那个位置
7. ++*cp
相当于:
++ ( *cp )
它返回一个字符b,ch的值变为字符b,cp还是指向ch。
8. (*cp)++
它返回一个字符a,ch的值变为字符b,cp还是指向ch。
9. ++*++cp
相当于:
( ++ ( * ( ++cp ) ) )
它返回一个ch后面那个位置的值的结果加上1,ch后面那个位置的结果变为原来的结果加上1,cp指向了ch后面那个位置。
10.++*cp++
相当于:
( ++ (* ( cp++ ) ) )
它返回一个字符b,ch的值变为字符b,cp指向ch后面那个位置。
11. 示例程序
-
字符串长度
#include<stdlib.h> size_t strlen(char *string) { int length = 0; //依次访问字符串的内容,计数字符串,知道遇见NUL终止符 while(*string++ != '\0') length += 1; return length; }
-
在一组字符串中查找:版本1
/* **给定一个指向以NULL结尾的指针列表的指针,在列表中的字符串中查找一个特定的字符。 */ #include<stdio.h> #define TURE 1 #define FALSE 0 int find_char(char **strings,char value) { char *string; //我们当前正在查找的字符串 /* **对于列表的每个字符串... */ while((string = *strings++ ) != NULL) /* **观察字符串中的每个字符,看看它是不是我们所需要查找的那个。 */ while(*string != '\0') if(*string++ == value) return TRUE; }
函数的参数是strings和value,strings是一个指向数组的指针,value是我们要查找的字符值。指针数组以一个NULL字节结束。
-
在一组字符串中查找:版本2
/***给定一个指向以NULL结尾的指针列表的指针,在列表中的字符串中查找一个特定的字符。**这个函数将会破坏这些指针,所以它只适用于这组字符串只使用一次的情况。*/#include<stdio.h>#include<assert.h>#define TURE 1#define FALSE 0int find_char(char **strings,char value){ assert(strings != NULL) /* **对于列表的每个字符串... */ while(*strings != NULL) /* **观察字符串中的每个字符,看看它是不是我们所需要查找的那个。 */ while( **string != '\0') { if(*(*string)++ == value) return TRUE; } return FALSE;}
这个程序和上面那个程序实现相同的功能,但是它不需要对每个字符串进行复制,由于邨彩副作用,这个程序将会破坏这个指针数组。这个副作用使得它不弱前面那个版本的程序好用,因为它只适用于字符串只需要查找一次的情况。