先来看一段示例程序
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);
原文:http://www.cnblogs.com/slfblog/p/4890217.html