这篇博客将通过整型数组、字符数组、字符串放在数组中、以及二维数组的数组名与&数组名和各类特殊情况的题目讲解来使得我们对于指针与数组名具有更加深刻的了解。
注意:
sizeof(数组名) - 数组名表示整个数组的-计算的是整个数组的大小
&数组名 - 数组名表示整个数组,取出的是整个数组的地址
除此之外,所有的数组名都是数组首元素的地址 !!!
1.整型数组
//sizeof(数组名) - 数组名表示整个数组的-计算的是整个数组的大小
//&数组名 - 数组名表示整个数组,取出的是整个数组的地址
//除此之外,所有的数组名都是数组首元素的地址
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//16 - sizeof(数组名),计算的是整个数组的大小因此结果为:16
printf("%d\n",sizeof(a+0));//4/8 - 不是数组名,因此表示的是数组首元素的地址的大小
//因此64位平台是8,32位平台是4
printf("%d\n",sizeof(*a));//4 - a表示首元素的地址解引用访问的一个元素int
printf("%d\n",sizeof(a+1));//4/8 - 表示的是数组第一个元素的地址的大小
printf("%d\n",sizeof(a[1]));//4 - 第二个元素的大小
printf("%d\n",sizeof(&a));//4/8 - &a虽然数组的地址,但是也是地址,sizeof (&a)计算的是一个地址的大小
printf("%d\n",sizeof(*&a));//16 - 计算的数组的大小
printf("%d\n",sizeof(&a+1));//4/8 - &a + 是数组后面的空间的地址
printf("%d\n",sizeof(&a[0]));//4/8 - 第一个元素的地址的大小
printf("%d\n",sizeof(&a[0]+1));//4/8 - 第二个元素的地址的大小
2.字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr+0));//4/8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4/8
printf("%d\n", sizeof(&arr+1));//4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8
printf("%d\n", strlen(arr));//随机值 - strlen是找'\0',而此时数组里面没有存放'\0',必然会访
//问数组后面的内容
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen((const char*) *arr));//err
printf("%d\n", strlen((const char*) arr[1]));//err
printf("%d\n", strlen((const char*) &arr));//随机值
printf("%d\n", strlen((const char*) (&arr + 1)));//随机值-6
printf("%d\n", strlen(&arr[0] + 1));//随机值-1
printf("%d\n", strlen((const char*) *arr)); //err
printf("%d\n", strlen((const char*) arr[1]));//err
*arr找到了数组中的'a',而'a'的Ascll码表值是97,而strlen函数会把97看成地址,97的16进制便是0x00000061,便出现如上图所示的错误。arr[1]也是同样的道理
3.字符串放在数组中
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7,该种方式数组里面存放的是:[a b c d e f \0]
printf("%d\n", sizeof(arr+0));//4/8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4/8
printf("%d\n", sizeof(&arr+1));//4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8
printf("%d\n", strlen(arr));//6 [a b c d e f \0]
printf("%d\n", strlen(arr+0));//6
printf("%d\n", strlen(*arr));//err
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen((const char*) &arr));//6
printf("%d\n", strlen((const char*) (&arr+1)));//随机值
printf("%d\n", strlen(&arr[0]+1));//5
char *p = "abcdef";//这是把a的地址放在了指针变量p中
printf("%d\n", sizeof(p));//4/8
printf("%d\n", sizeof(p+1));//4/8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//1
printf("%d\n", sizeof(&p));//4/8
printf("%d\n", sizeof(&p+1));//4/8
printf("%d\n", sizeof(&p[0]+1));//4/8
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p+1));//5
printf("%d\n", strlen(*p));//err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机
printf("%d\n", strlen(&p+1));//随机
printf("%d\n", strlen(&p[0]+1));//5
我们不但要知道结果是什么更应该知道它所对应的空间及其地址,如下所示:
printf("%d\n", sizeof(p));//4/8
printf("%d\n", sizeof(p+1));//4/8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//1
printf("%d\n", sizeof(&p));//4/8
printf("%d\n", sizeof(&p+1));//4/8
printf("%d\n", sizeof(&p[0]+1));//4/8
printf("%d\n", strlen(&p));//随机
printf("%d\n", strlen(&p+1));//随机
这两个随机值不存在联系,因为P中所存放的地址不确定,如:0x11223344,那这两个随机值便差了四个字节,但如果是0x11220044,\0在地址中出现那么&P便是两个字节,所以这两个随机值不存在必然的联系。
4.二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//48 - 数组名放在sizeof内部表示整个数组,因此3*4*4=48
printf("%d\n",sizeof(a[0][0]));//4
printf("%d\n",sizeof(a[0]));//16 - a[0]可以看成二维数组中的第一行的“一维数组”的数组名
//因此也便是第一行的“一维数组”的数组名放在了sizeof内部
printf("%d\n",sizeof(a[0]+1));//4/8 - a[0]+1是二维数组中的第一行的第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1)));//4 - 计算的是a[0]+1是二维数组中的第一行的第二个元素的大小
printf("%d\n",sizeof(a+1));//4/8 - a表示二维数组的首元素地址,即第一行的“一维数组”的地址
//则a+1表示第二行的“一维数组”的地址
printf("%d\n",sizeof(*(a+1)));//16 - 计算的是第二行的“一维数组”的大小
printf("%d\n",sizeof(&a[0]+1));//4/8 - &a[0]取出的是二维数组中的第一行的“一维数组”的地址
//则&a[0]+1表示第二行的“一维数组”的地址
printf("%d\n",sizeof(*(&a[0]+1)));//16 - 计算的是第二行的“一维数组”的大小
printf("%d\n",sizeof(*a));//16 - 第一行的“一维数组”的大小
printf("%d\n",sizeof(a[3]));//16 - a[3]其实是第四行的数组名 (如果有的话)
//所以其实不存在,也能通过类型计算大小的
在上述二维数组中比较难以理解的便是 a[0] 、 a+1 、&a[0]+1 、a[3],下面对其进行讲解:
对于二维数组如果把每一行都看作成一个一维数组那么a[0]就可以看作成一维数组的数组名,所以a[0]在sizeof(数组名)与&数组名情况之外下表示的是第一行的首元素的地址,&a[0]也就是取出的是第一行的一维数组的地址。
对a这个二维数组的数组名,它依然在sizeof(数组名)与&数组名情况之外下就表示首元素的地址,但是对于二维数组数组名所表示的首元素就是第一行。
对于a[3],这一空间随超出了我们所定义的二维数组的空间,但是sizeof内部是不参与运算的,因此也便不会产生越界访问的情况,至于16的计算是因为,sizeof所计算的是类属性,是按照一维数组的属性进行计算。