《5.1 Pointers and Addresses》
*ip += 1
将ip指向的内容加1,等同于 ++*ip
和 (*ip)++
,其中 (*ip)++
的括号是必须的,因为*和++都是由右往左联合。
《5.2 Pointers and Function Argument》
C使用按值传递的方式传递参数给函数。被调用函数 the called function 无法通过直接的方式改变调用函数 the calling function 的变量。
《5.3 Pointers and Arrays》
假设int a[10]和int *pa,pa = &a[O],则pa和a的值一样。
因为数组的名字是最初的元素位置的同义词,所以pa = &a[O]可以写成pa = a。
a[i]可以写成(a+i),**C会间接将a[i]转化为`(a+i)**。&a[i]等同于a+i。简单来讲, **array-and-index 的表达式等价于写成 a pointer and offset 的表达式**。
[]优先级高于
,X[ii][j]等价于
((X+ii))[j]但不等价于
*(X+ii)[j]`。
指针和数组名的区别:指针是变量,pa=a和pa++是合法的;数组名不是变量,a=pa和a++是不合法的。传递一个数组名给函数时,传递的是首元素的位置,对被调用函数而言,该函数参数就是一个指针,一个包含地址的变量。
int a[5]={1,2,3,4,5};int *ptr=(int *)(&a+1);
数组名就是数组0号元素的地址,a = &a[0]。&a是指向一个有5个整型元素的数组的地址,int *ptr=(int*)(&a+1) => int *ptr=(int*)(a地址 + sizeof(a));
,sizeof(a) = 5*sizeof(int)
。而printf("%p\n", iArry);
和printf("%p\n", &iArry);
输出的地址值是一致的,这说明底层实现并没有为二级指针创建临时变量什么的,而只是在计算一级指针和二级指针的方式上有所区别。
《5.4 Address Arithmetic》
指针和整数不能互换,0则是特例,指针可被赋值0,也可以和0作比较。C保证 0 永远不会是数据的合法地址,可以通过返回 0 (函数返回值为指针类型)来标识异常事件。符号常量NULL定义于stdio.h,代表一个指针的特殊值,经常用于代替0。
当两个指针指向不同的数组时,指针之间的运算或比较是未定义的。但存在一个特例:超出数组末端的第一个元素的地址可以用于指针运算,如:int array[10]; int* a = array + 10;
指针减法:指向相同数组的两个指针p和q,如果p < q,q-p+1将返回从p到q的元素个数。
《5.5 Character Pointers and Functions》
strcpy函数的实现:1
2
3
4
5
6
7
8
9array版本
/* strcpy: copy t to s; array subscript version */
void strcpy(char *s, char *t)
{
int i;
i = 0;
while ((s[i] = t[i]) != '\0')
i++;
}
1 | pointers版本1 |
1 | pointers版本2 |
1 | pointers版本3 |
strcmp函数的实现:1
2
3
4
5
6
7
8
9
10array版本
/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == '\0')
return 0;
return s[i] - t[i];
}
1 | pointers版本 |
练习
练习5-3:实现strcat(s,t)函数(Chapters 2)的指针版本,将字符串t复制到s的末端。1
2
3while(*s++); /* Get to the end of the string */
s--; /*get back to the end of the string.*/
while((*s++ = *t++));
练习5-4:实现strend(s,t)函数,如果字符串t出现在s的末端,返回1,否则返回0。1
2
3
4
5
6
7
8
9
10
11
12int strend(char *s, char *t)
{
char *sc = s;
char *tc = t;
while (*s != '\0')
s++;
while (*t != '\0')
t++;
while (s > sc && t > tc && *s-- == *t--) ;
return (t == tc && *s == *t ? 1 : 0);
}
练习5-5:实现strncpy(s,t,n)、strncat(s,t,n)、strncmp(s,t,n)函数,至多操作参数字符串的前n个字符。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30char *_strncpy(char *s, const char *ct, size_t n) {
char *p;
p = s;
for (; n > 0 && *ct != '\0'; --n)
*p++ = *ct++;
for (; n > 0; --n)
*p++ = '\0';
return s;
}
char *_strncat(char *s, const char *ct, size_t n) {
char *p;
p = s;
while (*p != '\0')
++p;
for (; n > 0 && *ct != '\0'; --n)
*p++ = *ct++;
*p = '\0';
return s;
}
//库函数strncmp("a", "b",0)会返回0
int _strncmp(char *s, char *t,int n)
{
for ( ; n>0 && *s == *t; s++, t++,n--)
if (*s == '\0' )
return 0;
if(n==0 ) return 0;
return *s - *t;
}