指针是C语言中广泛使用的一种数据类型。运用指针编程是C语言最主要的风格之一。
利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编语言一样
处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。学习指针是
学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志。
同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要
多编程,上机调试。只要作到这些,指针也是不难掌握的。
10.1 地址指针的基本概念
在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个
内存单元,不同的数据类型所占用的内存单元数不等,如整型量占 2 个单元,字符量占 1
个单元等,在前面已有详细的介绍。为了正确地访问这些内存单元,必须为每个内存单元编
上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。
既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指
针。 内存单元的指针和内存单元的内容是两个不同的概念。 可以用一个通俗的例子来说明
它们之间的关系。我们到银行去存取款时, 银行工作人员将根据我们的帐号去找我们的存
款单, 找到之后在存单上写入存款、取款的金额。在这里,帐号就是存单的指针, 存款数
是存单的内容。对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元
的内容。在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指
针变量的值就是某个内存单元的地址或称为某内存单元的指针。
图中,设有字符变量 C,其内容为“K”(ASCII 码为十进制数 75),C 占用了 011A 号单元
(地址用十六进数表示)。设有指针变量 P,内容为 011A,这种情况我们称为 P 指向变量 C,
或说 P 是指向变量 C 的指针。
严格地说,一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指
针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们中约定:“指针”是指地
址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问
内存单元。
既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数
据结构的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢? 因为数
组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址,也就找到了该数
组或函数。这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指
针变量中赋予数组或函数的首地址即可。这样做,将会使程序的概念十分清楚,程序本身也
精练,高效。在C语言中,一种数据类型或数据结构往往都占有一组连续的内存单元。 用
“地址”这个概念并不能很好地描述一种数据类型或数据结构,而“指针”虽然实际上也是一
个地址,但它却是一个数据结构的首地址,它是“指向”一个数据结构的,因而概念更为清
楚,表示更为明确。 这也是引入“指针”概念的一个重要原因。
10.2 变量的指针和指向变量的指针变量
10.2.1定义一个指针变量
10.2.2指针变量的引用
【例 10.1】
#include <stdio.h>main()
{int a, b;int *pointer_1, *pointer_2;a = 100;b = 10;pointer_1 = &a;pointer_2 = &b;printf("%d,%d\n", a, b);printf("%d,%d\n", *pointer_1, *pointer_2);
}
【例 10.2】输入 a 和 b 两个整数,按先大后小的顺序输出 a 和 b。
#include <stdio.h>main()
{int *p1, *p2, *p, a, b;scanf("%d,%d", &a, &b);p1 = &a;p2 = &b;if (a < b){p = p1;p1 = p2;p2 = p;}printf("\na=%d,b=%d\n", a, b);printf("max=%d,min=%d\n", *p1, *p2);
}
10.2.3指针变量作为函数参数
【例 10.3】题目同例 10.2,即输入的两个整数按大小顺序输出。今用函数处理,而且用指
针类型的数据作函数参数。
#include <stdio.h>swap(int *p1, int *p2)
{int temp;temp = *p1;*p1 = *p2;*p2 = temp;
}
main()
{int a, b;int *pointer_1, *pointer_2;scanf("%d,%d", &a, &b);pointer_1 = &a;pointer_2 = &b;if (a < b)swap(pointer_1, pointer_2);printf("\n%d,%d\n", a, b);
}
【例 10.4】请注意,不能企图通过改变指针形参的值而使指针实参的值改变。
#include <stdio.h>swap(int *p1, int *p2)
{int *p;p = p1;p1 = p2;p2 = p;
}
main()
{int a, b;int *pointer_1, *pointer_2;scanf("%d,%d", &a, &b);pointer_1 = &a;pointer_2 = &b;if (a < b)swap(pointer_1, pointer_2);printf("\n%d,%d\n", *pointer_1, *pointer_2);
}
【例 10.5】输入 a、b、c3 个整数,按大小顺序输出。
#include <stdio.h>swap(int *pt1, int *pt2)
{int temp;temp = *pt1;*pt1 = *pt2;*pt2 = temp;
}
exchange(int *q1, int *q2, int *q3)
{if (*q1 < *q2)swap(q1, q2);if (*q1 < *q3)swap(q1, q3);if (*q2 < *q3)swap(q2, q3);
}
main()
{int a, b, c, *p1, *p2, *p3;scanf("%d,%d,%d", &a, &b, &c);p1 = &a;p2 = &b;p3 = &c;exchange(p1, p2, p3);printf("\n%d,%d,%d \n", a, b, c);
}
10.2.4指针变量几个问题的进一步说明
【例 10.6】
#include <stdio.h>main()
{int a = 5, *p = &a;printf("%d", *p);
}
【例 10.7】
#include <stdio.h>main()
{int a = 10, b = 20, s, t, *pa, *pb; /*说明 pa,pb 为整型指针变量*/pa = &a; /*给指针变量 pa 赋值,pa 指向变量 a*/pb = &b; /*给指针变量 pb 赋值,pb 指向变量 b*/s = *pa + *pb; /*求 a+b 之和,(*pa 就是 a,*pb 就是 b)*/t = *pa * *pb; /*本行是求 a*b 之积*/printf("a=%d\nb=%d\na+b=%d\na*b=%d\n", a, b, a + b, a * b);printf("s=%d\nt=%d\n", s, t);
}
【例 10.8】
#include <stdio.h>main()
{int a, b, c, *pmax, *pmin; /*pmax,pmin 为整型指针变量*/printf("input three numbers:\n"); /*输入提示*/scanf("%d%d%d", &a, &b, &c); /*输入三个数字*/if (a > b){ /*如果第一个数字大于第二个数字...*/pmax = &a; /*指针变量赋值*/pmin = &b;} /*指针变量赋值*/else{pmax = &b; /*指针变量赋值*/pmin = &a;} /*指针变量赋值*/if (c > *pmax)pmax = &c; /*判断并赋值*/if (c < *pmin)pmin = &c; /*判断并赋值*/printf("max=%d\nmin=%d\n", *pmax, *pmin); /*输出结果*/
}
10.3 数组指针和指向数组的指针变量
10.3.1指向数组元素的指针
10.3.2通过指针引用数组元素
【例 10.9】输出数组中的全部元素。(下标法)
#include <stdio.h>main()
{int a[10], i;for (i = 0; i < 10; i++)a[i] = i;for (i = 0; i < 5; i++)printf("a[%d]=%d\n", i, a[i]);
}
【例 10.10】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)
#include <stdio.h>main()
{int a[10], i;for (i = 0; i < 10; i++)*(a + i) = i;for (i = 0; i < 10; i++)printf("a[%d]=%d\n", i, *(a + i));
}
【例 10.11】输出数组中的全部元素。(用指针变量指向元素)
#include <stdio.h>main()
{int a[10], I, *p;p = a;for (i = 0; i < 10; i++)*(p + i) = i;for (i = 0; i < 10; i++)printf("a[%d]=%d\n", i, *(p + i));
}
【例 10.12】
#include <stdio.h>main()
{int a[10], i, *p = a;for (i = 0; i < 10;){*p = i;printf("a[%d]=%d\n", i++, *p++);}
}
几个注意的问题:
- 指针变量可以实现本身的值的改变。如 p++是合法的;而 a++是错误的。因为 a 是数组
名,它是数组的首地址,是常量。 - 要注意指针变量的当前值。请看下面的程序。
【例 10.13】找出错误。
#include <stdio.h>main()
{int *p, i, a[10];p = a;for (i = 0; i < 10; i++)*p++ = i;for (i = 0; i < 10; i++)printf("a[%d]=%d\n", i, *p++);
}
【例 10.14】改正。
#include <stdio.h>main()
{int *p, i, a[10];p = a;for (i = 0; i < 10; i++)*p++ = i;p = a;for (i = 0; i < 10; i++)printf("a[%d]=%d\n", i, *p++);
}
- 从上例可以看出,虽然定义数组时指定它包含 10 个元素,但指针变量可以指到数组以
后的内存单元,系统并不认为非法。 - p++,由于++和同优先级,结合方向自右而左,等价于*(p++)。
- (p++)与(++p)作用不同。若 p 的初值为 a,则*(p++)等价 a[0],*(++p)等价 a[1]。
- (*p)++表示 p 所指向的元素值加 1。
- 如果 p 当前指向 a 数组中的第 i 个元素,则
*(p–)相当于 a[i–];
*(++p)相当于 a[++i];
*(–p)相当于 a[–i]。
10.3.3数组名作函数参数
同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函
数的参数使用。
【例 10.15】
#include <stdio.h>float aver(float *pa);
main()
{float sco[5], av, *sp;int i;sp = sco;printf("\ninput 5 scores:\n");for (i = 0; i < 5; i++)scanf("%f", &sco[i]);av = aver(sp);printf("average score is %5.2f", av);
}
float aver(float *pa)
{int i;float av, s = 0;for (i = 0; i < 5; i++)s = s + *pa++;av = s / 5;return av;
}
【例 10.16】将数组 a 中的 n 个整数按相反顺序存放。
算法为:将 a[0]与 a[n-1]对换,再 a[1]与 a[n-2] 对换……,直到将 a[(n-1/2)]与
a[n-int((n-1)/2)]对换。今用循环处理此问题,设两个“位置指示变量”i 和 j,i 的初值为
0,j 的初值为 n-1。将 a[i]与 a[j]交换,然后使 i 的值加 1,j 的值减 1,再将 a[i]与 a[j]
交换,直到 i=(n-1)/2 为止,如图所示。
#include <stdio.h>void inv(int x[], int n) /*形参x是数组名*/
{int temp, i, j, m = (n - 1) / 2;for (i = 0; i <= m; i++){j = n - 1 - i;temp = x[i];x[i] = x[j];x[j] = temp;}return;
}
main()
{int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};printf("The original array:\n");for (i = 0; i < 10; i++)printf("%d,", a[i]);printf("\n");inv(a, 10);printf("The array has benn inverted:\n");for (i = 0; i < 10; i++)printf("%d,", a[i]);printf("\n");
}
对此程序可以作一些改动。将函数 inv 中的形参 x 改成指针变量。
【例 10.17】对例 10.16 可以作一些改动。将函数 inv 中的形参 x 改成指针变量。
程序如下:
#include <stdio.h>void inv(int *x, int n) /*形参x为指针变量*/
{int *p, temp, *i, *j, m = (n - 1) / 2;i = x;j = x + n - 1;p = x + m;for (; i <= p; i++, j--){temp = *i;*i = *j;*j = temp;}return;
}
main()
{int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};printf("The original array:\n");for (i = 0; i < 10; i++)printf("%d,", a[i]);printf("\n");inv(a, 10);printf("The array has benn inverted:\n");for (i = 0; i < 10; i++)printf("%d,", a[i]);printf("\n");
}
执行结果
The original array:
3,7,9,11,0,6,7,5,4,2,
The array has benn inverted:
2,4,5,7,6,0,11,9,7,3,
【例 10.18】从 0 个数中找出其中最大值和最小值。
调用一个函数只能得到一个返回值,今用全局变量在函数之间“传递”数据。程序如下:
#include <stdio.h>int max, min; /*全局变量*/
void max_min_value(int array[], int n)
{int *p, *array_end;array_end = array + n;max = min = *array;for (p = array + 1; p < array_end; p++)if (*p > max)max = *p;else if (*p < min)min = *p;return;
}
main()
{int i, number[10];printf("enter 10 integer umbers:\n");for (i = 0; i < 10; i++)scanf("%d", &number[i]);max_min_value(number, 10);printf("\nmax=%d,min=%d\n", max, min);
}
说明:
- 在函数 max_min_value 中求出的最大值和最小值放在 max 和 min 中。由于它们是全局,
因此在主函数中可以直接使用。 - 函数 max_min_value 中的语句:
max=min=*array;
array 是数组名,它接收从实参传来的数组 numuber 的首地址。
array 相当于(&array[0])。上述语句与 max=min=array[0];等价。 - 在执行 for 循环时,p 的初值为 array+1,也就是使 p 指向 array[1]。以后每次执行 p++,
使 p 指向下一个元素。每次将*p 和 max 与 min 比较。将大者放入 max,小者放 min。 - 函数 max_min_value 的形参 array 可以改为指针变量类型。实参也可以不用数组名,而
用指针变量传递地址。
【例 10.19】程序可改为:
#include <stdio.h>int max, min; /*全局变量*/
void max_min_value(int *array, int n)
{int *p, *array_end;array_end = array + n;max = min = *array;for (p = array + 1; p < array_end; p++)if (*p > max)max = *p;else if (*p < min)min = *p;return;
}
main()
{int i, number[10], *p;p = number; /*使p指向number数组*/printf("enter 10 integer umbers:\n");for (i = 0; i < 10; i++, p++)scanf("%d", p);p = number;max_min_value(p, 10);printf("\nmax=%d,min=%d\n", max, min);
}
【例 10.20】用实参指针变量改写将 n 个整数按相反顺序存放。
#include <stdio.h>void inv(int *x, int n)
{int *p, m, temp, *i, *j;m = (n - 1) / 2;i = x;j = x + n - 1;p = x + m;for (; i <= p; i++, j--){temp = *i;*i = *j;*j = temp;}return;
}
main()
{int i, arr[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}, *p;p = arr;printf("The original array:\n");for (i = 0; i < 10; i++, p++)printf("%d,", *p);printf("\n");p = arr;inv(p, 10);printf("The array has benn inverted:\n");for (p = arr; p < arr + 10; p++)printf("%d,", *p);printf("\n");
}
注意:main 函数中的指针变量 p 是有确定值的。即如果用指针变作实参,必须现使指针变
量有确定值,指向一个已定义的数组。
【例 10.21】用选择法对 10 个整数排序。
#include <stdio.h>main()
{int *p, i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};printf("The original array:\n");for (i = 0; i < 10; i++)printf("%d,", a[i]);printf("\n");p = a;sort(p, 10);for (p = a, i = 0; i < 10; i++){printf("%d ", *p);p++;}printf("\n");
}
sort(int x[], int n)
{int i, j, k, t;for (i = 0; i < n - 1; i++){k = i;for (j = i + 1; j < n; j++)if (x[j] > x[k])k = j;if (k != i){t = x[i];x[i] = x[k];x[k] = t;}}
}
说明:函数 sort 用数组名作为形参,也可改为用指针变量,这时函数的首部可以改为:
sort(int *x,int n) 其他可一律不改。
10.3.4指向多维数组的指针和指针变量
【例 10.22】
#include <stdio.h>main()
{int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};printf("%d,", a);printf("%d,", *a);printf("%d,", a[0]);printf("%d,", &a[0]);printf("%d\n", &a[0][0]);printf("%d,", a + 1);printf("%d,", *(a + 1));printf("%d,", a[1]);printf("%d,", &a[1]);printf("%d\n", &a[1][0]);printf("%d,", a + 2);printf("%d,", *(a + 2));printf("%d,", a[2]);printf("%d,", &a[2]);printf("%d\n", &a[2][0]);printf("%d,", a[1] + 1);printf("%d\n", *(a + 1) + 1);printf("%d,%d\n", *(a[1] + 1), *(*(a + 1) + 1));
}
【例 10.23】
#include <stdio.h>main()
{int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};int(*p)[4];int i, j;p = a;for (i = 0; i < 3; i++){for (j = 0; j < 4; j++)printf("%2d ", *(*(p + i) + j));printf("\n");}
}
10.4 字符串的指针指向字符串的针指变量
10.4.1字符串的表示形式
C 语言中,可以用两种方法访问一个字符串。
1) 用字符数组存放一个字符串,然后输出该字符串。
【例 10.24】
#include <stdio.h>main()
{char string[] ="I love China !";printf("%s\n", string);
}
【例 10.25】
#include <stdio.h>main()
{char *string ="I love China !";printf("%s\n", string);
}
【例 10.26】输出字符串中 n 个字符后的所有字符。
#include <stdio.h>main()
{char *ps = "this is a book";int n = 10;ps = ps + n;printf("%s\n", ps);
}
【例 10.27】在输入的字符串中查找有无‘k’字符。
#include <stdio.h>main()
{char st[20], *ps;int i;printf("input a string:\n");ps = st;scanf("%s", ps);for (i = 0; ps[i] != '\0'; i++)if (ps[i] == 'k'){printf("there is a 'k' in the string\n");break;}if (ps[i] == '\0')printf("There is no 'k' in the string\n");
}
【例 10.28】本例是将指针变量指向一个格式字符串,用在 printf 函数中,用于输出二维
数组的各种地址表示的值。但在 printf 语句中用指针变量 PF 代替了格式串。 这也是程序
中常用的方法。
#include <stdio.h>main()
{static int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};char *PF;PF = "%d,%d,%d,%d,%d\n";printf(PF, a, *a, a[0], &a[0], &a[0][0]);printf(PF, a + 1, *(a + 1), a[1], &a[1], &a[1][0]);printf(PF, a + 2, *(a + 2), a[2], &a[2], &a[2][0]);printf("%d,%d\n", a[1] + 1, *(a + 1) + 1);printf("%d,%d\n", *(a[1] + 1), *(*(a + 1) + 1));
}
**【例 10.29】本例是把字符串指针作为函数参数的使用。要求把一个字符串的内容复制到另
一个字符串中,并且不能使用 strcpy 函数。函数 cprstr 的形参为两个字符指针变量。pss
指向源字符串,pds 指向目标字符串。注意表达式:(pds=pss)!=`\0’的用法。
#include <stdio.h>cpystr(char *pss, char *pds)
{while ((*pds = *pss) != '\0'){pds++;pss++;}
}
main()
{char *pa = "CHINA", b[10], *pb;pb = b;cpystr(pa, pb);printf("string a=%s\nstring b=%s\n", pa, pb);
}
【例 10.30】简化后的程序如下所示。
#include <stdio.h>cpystr(char *pss, char *pds)
{while (*pds++ = *pss++);
}
main()
{char *pa = "CHINA", b[10], *pb;pb = b;cpystr(pa, pb);printf("string a=%s\nstring b=%s\n", pa, pb);
}
10.4.2使用字符串指针变量与字符数组的区别
10.5 函数指针变量
【例 10.31】本例用来说明用指针形式实现对函数调用的方法。
#include <stdio.h>int max(int a, int b)
{if (a > b)return a;elsereturn b;
}int main() // 注意main函数的返回类型应当是int,同时建议显式返回0表示程序正常结束
{int (*pmax)(int, int); // 指针的声明应明确参数类型,虽然在某些编译器上可省略,但明确指定更佳int x, y, z;pmax = max; // 此处无需更改printf("input two numbers:\n");scanf("%d%d", &x, &y);z = (*pmax)(x, y); // 此处无需更改printf("maximum=%d", z);return 0; // 添加return语句
}
10.6 指针型函数
【例 10.32】本程序是通过指针函数,输入一个 1~7 之间的整数,输出对应的星期名。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>char *day_name(int n); // 添加函数原型声明int main() // 建议明确指定main函数的返回类型为int
{int i;printf("input Day No:\n");scanf("%d", &i);if (i < 0)exit(1);printf("Day No:%2d-->%s\n", i, day_name(i));return 0; // 主函数正常结束应返回0
}char *day_name(int n)
{static char *name[] = {"Illegal day","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};return ((n < 1 || n > 7) ? name[0] : name[n]);
}
10.7 指针数组和指向指针的指针
10.7.1指针数组的概念
【例 10.33】通常可用一个指针数组来指向一个二维数组。指针数组中的每个元素被赋予
二维数组每一行的首地址,因此也可理解为指向一个一维数组。
#include <stdio.h>main()
{int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};int *pa[3] = {a[0], a[1], a[2]};int *p = a[0];int i;for (i = 0; i < 3; i++)printf("%d,%d,%d\n", a[i][2 - i], *a[i], *(*(a + i) + i));for (i = 0; i < 3; i++)printf("%d,%d,%d\n", *pa[i], p[i], *(p + i));
}
【例 10.34】指针数组作指针型函数的参数。在本例主函数中,定义了一个指针数组 name,
并对 name 作了初始化赋值。其每个元素都指向一个字符串。然后又以 name 作为实参调用
指针型函数 day_name,在调用时把数组名 name 赋予形参变量 name,输入的整数 i 作为第二
个实参赋予形参 n。在 day_ name 函数中定义了两个指针变量 pp1 和 pp2,pp1 被赋予 name[0]
的值(即name),pp2 被赋予 name[n]的值即(name+ n)。由条件表达式决定返回 pp1 或 pp2
指针给主函数中的指针变量 ps。最后输出 i 和 ps 的值。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>main()
{static char *name[] = {"Illegal day","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};char *ps;int i;char *day_name(char *name[], int n);printf("input Day No:\n");scanf("%d", &i);if (i < 0)exit(1);ps = day_name(name, i);printf("Day No:%2d-->%s\n", i, ps);
}
char *day_name(char *name[], int n)
{char *pp1, *pp2;pp1 = *name;pp2 = *(name + n);return ((n < 1 || n > 7) ? pp1 : pp2);
}
【例 10.35】输入 5 个国名并按字母顺序排列后输出。现编程如下:
#include "string.h"
#include <stdio.h>main()
{void sort(char *name[], int n);void print(char *name[], int n);static char *name[] = {"CHINA", "AMERICA", "AUSTRALIA","FRANCE", "GERMAN"};int n = 5;sort(name, n);print(name, n);
}
void sort(char *name[], int n)
{char *pt;int i, j, k;for (i = 0; i < n - 1; i++){k = i;for (j = i + 1; j < n; j++)if (strcmp(name[k], name[j]) > 0)k = j;if (k != i){pt = name[i];name[i] = name[k];name[k] = pt;}}
}
void print(char *name[], int n)
{int i;for (i = 0; i < n; i++)printf("%s\n", name[i]);
}
10.7.2指向指针的指针
【例 10.36】使用指向指针的指针。
#include <stdio.h> // 只保留必需的头文件int main() // 明确main函数的返回类型为int
{// 定义一个字符串数组char *names[] = {"Follow me","BASIC","Great Wall","FORTRAN","Computer design" // 修正拼写错误:desighn -> design};// 使用指针遍历并打印数组中的每个字符串for (int index = 0; index < 5; ++index) // 使用更直观的变量名,并使用++运算符置于变量后,这是一种常见的编码风格{char **pointer = names + index; // 明确指出此指针用于指向数组中的字符串printf("%s\n", *pointer);}return 0; // 程序成功执行完毕,返回0
}
【例 10.37】一个指针数组的元素指向数据的简单例子。
#include <stdio.h>main()
{static int a[5] = {1, 3, 5, 7, 9};int *num[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]};int **p, i;p = num;for (i = 0; i < 5; i++){printf("%d\t", **p);p++;}
}
10.7.3main 函数的参数
【例 10.38】
#include <stdio.h>main(int argc, char *argv)
{while (argc-- > 1)printf("%s\n", *++argv);
}
10.8 有关指针的数据类型和指针运算的小结
10.8.1有关指针的数据类型的小结
10.8.2指针运算的小结
现把全部指针运算列出如下:
- 指针变量加(减)一个整数:
例如:p++、p–、p+i、p-i、p+=i、p-=i
一个指针变量加(减)一个整数并不是简单地将原值加(减)一个整数,而是将该指针
变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数加(减)。 - 指针变量赋值:将一个变量的地址赋给一个指针变量。
p=&a; (将变量 a 的地址赋给 p)
p=array; (将数组 array 的首地址赋给 p)
p=&array[i]; (将数组 array 第 i 个元素的地址赋给 p)
p=max; (max 为已定义的函数,将 max 的入口地址赋给 p)
p1=p2; (p1 和 p2 都是指针变量,将 p2 的值赋给 p1)
注意:不能如下:
p=1000; - 指针变量可以有空值,即该指针变量不指向任何变量:
p=NULL; - 两个指针变量可以相减:如果两个指针变量指向同一个数组的元素,则两个指针变量值
之差是两个指针之间的元素个数。 - 两个指针变量比较:如果两个指针变量指向同一个数组的元素,则两个指针变量可以进
行比较。指向前面的元素的指针变量“小于” 指向后面的元素的指针变量。
10.8.3void 指针类型
ANSI 新标准增加了一种“void”指针类型,即可以定义一个指针变量,但不指定它是指向
哪一种类型数据。