现在的位置: 首页 > 08 指针 > 正文

数组的本质:常量指针

2011年09月27日 08 指针 ⁄ 共 57字 ⁄ 字号 暂无评论

数组的本质是常量指针

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题

抱歉!评论已关闭.