数组的本质是常量指针
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #define N 10 int main() { int i, a[N]; for(i=0; i<N; i++) a[i]=2*i+1; for(i=0; i<N; i++) printf("%4d", a[i]); return 0; } |
用指针也可以实现同样的功能
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #define N 10 int main() { int i, a[N], *p = a; // p 初始化为 a, 左星右方,有 * 和 [] 的都是地址 for(i=0; i<N; i++) p[i]=2*i+1; for(i=0; i<N; i++) printf("%4d", p[i]); return 0; } |
在实际应用中,很少看到这样的代码,因为这样做并没有提供任何优势。
请看下面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <string.h> #define N 20 int main() { int i; char s[N] = "Hello, World"; for(i=0 ; i<strlen(s); i++) putchar(s[i]); return 0; } |
这个例子逐个输出字符串s的各个字符。
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #define N 20 int main() { char s[N] = "Hello, World", *p; for(p=s; *p!='\0'; p++) putchar(*p); return 0; } |
下面的例子非常的典型,值得好好琢磨
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h> #include <string.h> #define N 20 int main() { int i; char s[N] = "Hello, World", *p; printf("%d\n", sizeof(s)); // 字符数组s占用的空间 printf("%d\n", strlen(s)); // 字符串 s 的长度 for(p=s; *p!='\0'; p++) // 绝对地址递增 printf("%p:%c\n", p, *p); printf("\n\n"); for(i=0; i<strlen(s); i++) // 偏移量 i 地址 printf("%p:%c\n", s+i, s[i]); // 起始地址 s + 偏移量 i return 0; } |
你可以认为 [] 和 * 是一样的。很典型的例子就是函数定义
1 2 3 | void bubble_sort(int v[], int n) 可以写为 void bubble_sort(int *v, int n) |
掌握 [] 和 * 的互换: *(p+i) 等价于 p[i]
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #define N 10 int main() { int i,a[N],*p=a; for(i=0; i<N; i++) *(p+i)=2*i+1; // 左 * 右 [] for(i=0; i<N; i++) printf("%4d", a[i]); return 0; } |
那么数组和指针就没有区别吗? 当然有!
数组 a 是常量,也就是说一旦确定之后,就不能再改变。 指针 p 是个变量,可以变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> #define N 10 int main() { int i, a[N], *p = a; for(i=0; i<N; i++) a[i]=2*i+1; printf("[%p]=%d\n", p, *p); p++; // 下一个地址 printf("[%p]=%d\n", p, *p); return 0; } |
保存double类型的数组和指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #define N 10 int main() { int i; double a[N]; double *p = a; for(i=0; i<N; i++) a[i]=2*i+1; printf("[%p]=%f\n", p, *p); p++; // 下一个地址 printf("[%p]=%f\n", p, *p); return 0; } |
在上面的程序中,你是不能把 p++ 写成 a++。
你可以认为,a 是地主,拥有固定的空间;而 p 则是访客。 p 可以今天去 a[0] (p = a),明天去 a[4] (p = a+4 或者 p = &a[4]), p是很逍遥的。。。
变量指针 p 必须指向已经分配空间的变量,在这个例子中是数组 a。
下面使用 sizeof 来看看 i a p 这三个变量的大小。
i 是 int 类型的,通常是32位(在Turbo C 2.0 环境中是16位),也就是 4个字节。 所以 sizeof(i) = 4
a 占用了10个int,每个 int 是 4个字节,那 sizeof(a) 该是多少?
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> int main() { int i, a[10], *p=a; printf("sizeof i=%d\n", sizeof(i)); printf("sizeof a=%d\n", sizeof(a)); printf("sizeof p=%d\n", sizeof(p)); return 0; } |
指针p是32位的,也就是4个字节,和类型无关。把上面程序中的 int 类型改为 double,你看看输出又是什么?
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> int main() { double i,a[10],*p=a; printf("sizeof i=%d\n", sizeof(i)); printf("sizeof a=%d\n", sizeof(a)); printf("sizeof p=%d\n", sizeof(p)); return 0; } |
2009年选择题第30题 2010秋选择题第29题 2011秋选择题第23题