指针和数组不一样

    先来看一段示例程序

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     char array[2][10];
 7 
 8     printf ("sizeof array: %d\n", (int)sizeof(array));
 9     printf ("The address of array is:       %p\n", &array);
10     printf ("The address of array[0] is:    %p\n", &array[0]);
11     printf ("The address of array[1] is:    %p\n", &array[1]);
12     printf ("array point at:                %p\n", array);
13     printf ("array[0] point at:             %p\n", array[0]);
14     printf ("array[1] point at:             %p\n", array[1]);
15     printf ("The address of array[0][0] is: %p\n", &array[0][0]);
16     printf ("The address of array[1][0] is: %p\n", &array[1][0]);
17 
18     printf ("*****************************************************\n");
19 
20     char **ptr;
21     ptr = malloc(2*sizeof(char *));
22     ptr[0] = malloc(10*sizeof(char));
23     ptr[1] = malloc(10*sizeof(char));
24 
25     printf ("sizeof ptr: %d\n", (int)sizeof(ptr));
26 //    printf ("ptr[0]: %d\n", (int)sizeof(ptr[0]));
27 //    printf ("ptr[1]: %d\n", (int)sizeof(ptr[1]));
28     printf ("The address of ptr is:       %p\n", &ptr);
29     printf ("The address of ptr[0] is:    %p\n", &ptr[0]);
30     printf ("The address of ptr[1] is:    %p\n", &ptr[1]);
31     printf ("ptr points at:               %p\n", ptr);
32     printf ("ptr[0] points at:            %p\n", ptr[0]);
33     printf ("ptr[1] points at:            %p\n", ptr[1]);
34     printf ("The address of ptr[0][0] is: %p\n", &ptr[0][0]);
35     printf ("The address of ptr[1][0] is: %p\n", &ptr[1][0]);
36 
37     return 0;
38 }

在程序中,我们先创建了一个二维数组array,而后又动态创建了一个二维数组ptr,然后分别打印相关变量的地址。当我们运行这段代码的时候,会出现下面的结果:

sizeof array: 20
The address of array is:       0x7fffc85d33b0
The address of array[0] is:    0x7fffc85d33b0
The address of array[1] is:    0x7fffc85d33ba
array point at:                0x7fffc85d33b0
array[0] point at:             0x7fffc85d33b0
array[1] point at:             0x7fffc85d33ba
The address of array[0][0] is: 0x7fffc85d33b0
The address of array[1][0] is: 0x7fffc85d33ba
*****************************************************
sizeof ptr: 8
The address of ptr is:       0x7fffc85d33a8
The address of ptr[0] is:    0x2367010
The address of ptr[1] is:    0x2367018
ptr points at:               0x2367010
ptr[0] points at:            0x2367030
ptr[1] points at:            0x2367050
The address of ptr[0][0] is: 0x2367030
The address of ptr[1][0] is: 0x2367050

当我们用sizeof关键字分别对array和ptr进行操作时,前者得到的恰好是数组的大小,而后者则返回ptr变量的大小(char **)。

静态数组的创建是在编译过程中,也就是说,在编译的时候,编译器就已经给array数组在栈上分配了连续的地址空间,其大小恰好就是20B(注意区分栈和堆,变量都存储在栈里边,堆是用来提供动态分配的空间)。ptr本身作为一个char**类型的变量,在编译时编译器为其在栈上分配了存储空间,其地址为0x7fffc85d33a8,然后通过malloc()创建了ptr[0]、ptr[1],注意,ptr[0]、ptr[1]都是在堆上的。其实,观察他们的地址可以发现,array、ptr的地址值都较大,而ptr[0]、ptr[1]的地址值都较小,这是因为堆在地址空间的下部,向上生长,栈在堆的上面,向下生长。

在C语言中,规定第一个元素的地址即为数组的地址,所以也就不难理解上面出现的结果。

关于数组和指针,还有一个问题。如果我们定义一个函数

void fun(char **para);

如果把array作为参数传入到这个函数中,编译器会报错

warning: passing argument 1 of ‘func’ from incompatible pointer type [enabled by default]
note: expected ‘char **’ but argument is of type ‘char (*)[2]’

什么意思呢,就是fun()函数希望传入一个char ** 类型的变量,但你却传入了一个char (*)[2](指向 指向char类型的指针  的指针)。C 语言中有一条赋值规则,右值应该可以经过类型转换变为左值得类型(比如左边是一个char类型,右边是一个int类型,编译器会隐式地把右边的int类型转换为char类型,然后进行赋值操作),但是显然char (*)[2]不能转换为char**,所以编译器就会报错了(c语言通过值传递进行函数调用,相当于赋值 para=array,关于更多类型转换的问题可以参见《Expert C》)。解决这个问题的办法也很简单,只要加上强制类型转换就可以了

fun((char **)array);

 

posted on 2015-10-18 20:40  songlingfei  阅读(203)  评论(0编辑  收藏  举报

导航