目录
前言
在学习c语言过程中,指针就像是妖魔鬼怪,形式多变,时不时隐身,出入在代码的各个角落,让我们为之抓狂。
为了深入了解和理解指针的内容,我们将会详细探讨一维数组,二维数组,数组指针,指针数组和指针有什么关系以及他们之间的互化关系。
一、训前热身
下面给出几组训练,试试是否可以正确写出输出的值
int a [] = { 1 , 2 , 3 , 4 };printf ( "%d\n" , sizeof ( a ));输出 4;
char arr [] = { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' };printf ( "%d\n" , sizeof ( arr ));输出 6;
char arr [] = "abcdef" ;printf ( "%d\n" , sizeof ( arr ));输出 7;
char * p = "abcdef" ;printf ( "%d\n" , sizeof ( p ));输出 1;
int a [ 3 ][ 4 ] = { 0 };printf ( "%d\n" , sizeof ( a ));输出 48;
看到这里,想必对于初学者或多或少会有些许疑问,这个为什么输出的答案是这个?那个怎么又变了?或者完全不懂为什么输出这个数字。接下来我会和大家深究答案为何而来
二、知识储备
sizeof()函数 :此函数计算的是某个类型的字节大小或空间大小,比如sizeof(int)=4(字节)
strlen()函数:此函数计算的是数组元素长度,比如strlen(“abcdef”)=6(字节)strlen计算长度时,遇到‘\0’停止计算;
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
三、训练开始
(1),一维数组笔试题分析
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
int main()
{
int a[] = { 1,2,3,4 };//1
printf("%d\n", sizeof(a));//解释:a是一个数组名 根据 1. 数组名a代表整个数组,计算的是整个数组的大小 答案 :4*4=16//2
printf("%d\n", sizeof(a + 0));//解释:a+0不满足 1. 中的条件(仅有数组名a在括号内)这此a为数组首元素地址//而且a+0带标跳过0个元素 即为首元素地址,指针(地址)的大小为4或8 答案:4 or 8;
//3
printf("%d\n", sizeof(*a));//解释:*a不满足 1. 的条件 数组名a为首元素地址 然后解引用得到的是整型元素 1 大小为 4//答案 :4
//4
printf("%d\n", sizeof(a + 1));//解释:同第二题 计算的是a+1处地址的大小 为 4 or 8 答案:4or8//5
printf("%d\n", sizeof(a[1]));//解释 a[1] 取出的是整型数组中的一个元素 大小为4 答案:4//6
printf("%d\n", sizeof(&a));//解释:&a 由 2. 知 代表整个数组的地址 求地址的大小即指针大小 为4or8 答案:4or8//7
printf("%d\n", sizeof(*&a));//解释:*&a=a 当*在&的前时 即*&可直接相抵消 由题一知 为16 答案 16//8
printf("%d\n", sizeof(&a + 1));//解释:&a+1 代表的还是一个地址 大小仍然为 4 or 8 答案:4or8//9
printf("%d\n", sizeof(&a[0]));//解释:取的是a[0]的地址 大小为 4 or 8 答案4or8//10
printf("%d\n", sizeof(&a[0] + 1));//解释:地址+1 还是地址 大小为 4 or 8 答案 4 or 8
return 0;}
1. 16
2. 4or8
3. 4
4. 4or8
5. 4
6. 4or8
7. 16
8. 4or8
9. 4or8
10. 4or8
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
代码运行结果:左:x86运行系统下 右:x64运行系统下
(2)字符数组
1.0
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
#include<stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };//char类型元素为字节大小为 1
//1.
printf("%d\n", sizeof(arr));//解释:由 ①知 arr 单列在sizeof中表示整个数组 求的是整个数组的大小 为1*6=6;
//2.
printf("%d\n", sizeof(arr + 0));//解释:不符合①的条件,表示求首元素地址大小 为 4 or 8;
//3.
printf("%d\n", sizeof(*arr));//解释:不符合①的条件,*arr表示求首元素的大小 为1
//4.
printf("%d\n", sizeof(arr[1]));//解释:求数组第二个元素的大小 为 1;
//5.
printf("%d\n", sizeof(&arr));//解释:&arr 表示取整个数组的地址 求地址大小 为 4or8;
//6.
printf("%d\n", sizeof(&arr + 1));//解释:&arr+1表示数组地址后面+1的地址 求地址大小 为4or8;
//7.
printf("%d\n", sizeof(&arr[0] + 1));//解释:&arr[0] + 1表示数组首元素后面一个元素的地址 求地址大小 为4or8;
//8.
printf("%d\n", strlen(arr));//解释:strlen(arr)求字符串长度遇到'\0'停止,此数组中无‘\0'将会遇到’\0‘停止 为随机值;
//9.
printf("%d\n", strlen(arr + 0));//解释:同8. 为随机值
//10
//printf("%d\n", strlen(*arr));//解释:*arr 表示首元素a 我们传进去必须是一个地址 为err
//11.
//printf("%d\n", strlen(arr[1]));//解释:同 10.
printf("err\n");
printf("err\n");//运行结果会报错 屏蔽掉打印err
//12.
printf("%d\n", strlen(&arr));//解释:&arr表示整个数组的地址,从第一个元素的地址开始计算长度无结束符 为随机值;
//13.
printf("%d\n", strlen(&arr + 1));//解释:&arr+1表示整个数组后面的一个元素的地址开始计算,无结束符 为 随机值-6
//14.
printf("%d\n", strlen(&arr[0] + 1));//解释:&arr[0] + 1表示从数组的第二个元素的地址开始计算 无结束符 为 随机值-1
}1. 6
2. 4or8
3. 1
4. 1
5. 4or8
6. 4or8
7. 4or8
8. 随机值
9.随机值
10.err
11.err
12.随机值
13.随机值-6
14.随机值-1
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
代码运行结果如下:
2.0
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
#include<stdio.h>
int main()
{char arr[] = "abcdef";//此数组中最后一个元素是’\0‘
//1.
printf("%d\n", sizeof(arr));//解释:由①知,计算的是整个数组的大小 为 7
//2.
printf("%d\n", sizeof(arr + 0));//解释:不满足① arr+0表示首元素的地址 求地址大小为 4or8
//3.
printf("%d\n", sizeof(*arr));//解释:*arr表示首元素 求元素字节为 1
//4.
printf("%d\n", sizeof(arr[1]));//解释:arr[1]表示数组第二个元素 求元素字节为 1
//5.
printf("%d\n", sizeof(&arr));//解释:&arr表示取整个数组的地址 求地址大小为 4or8
//6.
printf("%d\n", sizeof(&arr + 1));//解释:&arr + 1表示数组后的第一个元素的地址,求地址大小为 4or8
//7.
printf("%d\n", sizeof(&arr[0] + 1));//解释:求地址大小为 4or8//8.
printf("%d\n", strlen(arr));//解释:从首元素开始到’\0‘结束为 6
//9.
printf("%d\n", strlen(arr + 0));//解释:同8. 为6
10.
//printf("%d\n", strlen(*arr));//解释:err
11.
//printf("%d\n", strlen(arr[1]));//解释:err
printf("err\n");
printf("err\n");
//12.
printf("%d\n", strlen(&arr));//解释:从数组首元素地址开始计算到’\0‘结束为6
//13.
printf("%d\n", strlen(&arr + 1));//解释:从数组后的一个元素地址开始计算到’\0‘结束 为随机值
//14.
printf("%d\n", strlen(&arr[0] + 1));//解释:从数组第二个元素地址开始计算到’\0‘结束为5
}1. 7
2. 4or8
3. 1
4. 1
5. 4or8
6. 4or8
7. 4or8
8. 6
9. 6
10.err
11.err
12.6
13.随机值
14.5
#include<stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
}
代码运行结果如下:
3.0
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
#include<stdio.h>
int main()
{
char* p = "abcdef";//p是一个char*型的指针变量指向的的是常量字符串"abcdef"的首地址 即字符a的地址
//强调 p是一个指针(地址)
//1.
printf("%d\n", sizeof(p));//解释:求地址p的大小为 4 or 8
//2.
printf("%d\n", sizeof(p + 1));//解释:求地址p+1的大小为 4 or 8
//3.
printf("%d\n", sizeof(*p));//解释:*p 表示取首地址的内容即字符a 求字符元素的大小为 1
//4.
printf("%d\n", sizeof(p[0]));//解释:p[0]=*(p+0) 即求字符a的大小为1
//5.
printf("%d\n", sizeof(&p));//解释:&p 表示是取指针p的地址 还是求地址的大小为 4or8
//6.
printf("%d\n", sizeof(&p + 1));//解释:求地址大小 为 4or8
//7.
printf("%d\n", sizeof(&p[0] + 1));//解释:求地址大小为 4or8//8.
printf("%d\n", strlen(p));//解释:p为数组首地址 从此处计算长度 到结束符结束 为6
//9.
printf("%d\n", strlen(p + 1));//解释:p+1为数组第二个元素地址 从此处计算长度 到结束符结束 为5
//printf("%d\n", strlen(*p));//解释:*p 解引用得到字符串"abcdef" 未知地址 err
//printf("%d\n", strlen(p[0]));//解释:同上
//10.
printf("err\n");
//11.
printf("err\n");
//12.
printf("%d\n", strlen(&p));//解释:&p 把指针变量p 存放在一个地址上 从此地址开始计算 到结束符结束 为随机值
//13.
printf("%d\n", strlen(&p + 1));//解释:&p 把指针变量p 存放在一个地址上 从此地址+1处开始计算 到结束符结束 为随机值
//14.
printf("%d\n", strlen(&p[0] + 1));//解释:p[0]=*(p+0) &p[0]即为一个元素a的地址然后跳过一个元素的地址 计算到结束符 为5
}1. 4 or 8
2. 4 or 8
3. 1
4. 1
5. 4or8
6. 4or8
7. 4or8
8. 6
9. 5
10.err
11.err
12.随机值
13.随机值
14.5
#include<stdio.h>
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p + 1));
printf("%d\n", strlen(&p[0] + 1));
}
代码运行结果如下:
(3)二维数组笔试题分析
①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;
②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;
除上述两种情况之外,所有的数组名都表示数组首元素的地址;
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };//a[3][4]二维数组 可看做有三个元素的一维数组,每个元素又是有四个元素一维数组
//1.
printf("%d\n", sizeof(a));//解释:数组名a表示 整个数组符合① 求数组总元素大小为 4*3*4=48
//2.
printf("%d\n", sizeof(a[0][0]));//解释:a[0][0] 表示求第一行第一列的元素的大小为 4
//3.
printf("%d\n", sizeof(a[0]));//解释:a[0]表示一个一维数组名, 符合①, 这个数组元素代表第一行,元素有四个 大小为 16
//4.
printf("%d\n", sizeof(a[0] + 1));//解释:a[0]表示第一行元素的地址在加一 那么这里表示地址 求地址大小为 4 or 8
//5.
printf("%d\n", sizeof(*(a[0] + 1)));//解释:a[0] + 1表示第一行首元素的地址加一 表示第一行第二列的地址,然后解引用 就是求元素的大小为4
// a[i]=*(a+i)----*(a[i] + j))=*(*(a+i) + j))=a[i][j]
//6.
printf("%d\n", sizeof(a + 1));//解释:a+1表示第一行第二列元素的地址 求地址大小为4or8
//7.
printf("%d\n", sizeof(*(a + 1)));//解释:*(a+1)=a[1] 表示一个一维数组 求该一维数组大小 大小为16
//8.
printf("%d\n", sizeof(&a[0] + 1));//解释:取把第一行地址的地址 然后+1 求地址大小为4or8
//9.
printf("%d\n", sizeof(*(&a[0] + 1)));//解释:&a[0] + 1说明是第二行地址的地址 然后解引用表示第二行求得大小为:4*4=16
//10.
printf("%d\n", sizeof(*a));//解释:*a=a[0]代表二维数组的首行 求得 大小为4*4=16
return 0;
}1. 48
2. 4
3. 16
4. 4 or 8
5. 4
6. 4or8
7. 16
8. 4 or 8
9. 16
10.16
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
return 0;
}
代码运行结如下: