二维数组:
如 char a[3][4] = {"aaa", "bbb", "ccc"};
那么内存中的排布是:
可以看出二维数组的元素仍然是地址连续的,
所以我们
要打印 "aaa" : printf("%s", (char *)a); // 这里将a强制转换类型:char (*)[4] -> char * ,当然这里不使用强制转换也行,
// 因为只需要给printf函数正确的地址就行了。
要打印"bbb": printf("%s", (char *)(a+1)); // 这里 a + 1,注意 a 是 char (*)[4],所以a+1实际上地址偏移 4*sizeof(char)
要打印"ccc" :printf("%s", (char *)(a+2));
当然也可以这样写:
printf("%s", a[0]); //这里 a[n]是一维数组,数组做右值表示数组首元素的首地址,a[n]的首元素是char类型,首地址就是char
//类型,所以不需要写成 printf("%s", (char *)a[0]);
printf("%s", a[1]);
printf("%s", a[2]);
说下为什么这个二维数组一般使用 char (*)[4]指向:
char (*p)[4] = a;
首先数组做右值,表示数组首元素的首地址,这里首元素是一个4个元素的一维数组,所以首地址就是以这个一维元素为单位取地址,首元素是char [4]类型,所以指针是 char (*)[4].
与二维数组容易混淆的是指针数组
如 char *[5]
这个指针数组在内存中排布如下:
可以看出 char *[5]的数组元素是指针,指针指向不同的 char *或者char[],
如果:
char *a[5] = {0}, char c = 'c', char str[] = "abc";
char **ap = a;
a[0] = &c;
a[1] = str;
printf("%c", *a[0]);
printf("%s", a[1]);
printf("%c", **(ap+0));
printf("%s", *(ap+1));
说下为什么用 char ** 指向指针数组,
因为指针数组也是数组,数组做右值表示首元素的首地址,这里首元素是char *类型,所以指向他的指针就是 char **类型。