指针和数组题解析
你认为你对数组和指针很了解吗?可以看看这些题,相信明白了之后你的水平也就挺强的了
今天的笔试题有8组,请耐心看完,谢谢
首先
strlen - 库函数
求字符串长度的,从起始位置往后数遇到'\0'就会停下来
sizeof - 操作符 - 单位是字节
求变量所占空间的大小
求类型创建的变量所占空间的大小
接下来带你学习一下笔试题。
第一组:
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));
你认为答案是多少呢?
想必已经思考过了。
接下来解析一下,你觉得你能对几道呢?
数组名:
1.sizeof(数组名) - 数组名表示整个元素,计算的是整个数组的大小。
2.&数组名 - 数组名表示整个数组,取出的是整个数组的地址。
3.除此之外,所有的数组名都是数组首元素的地址。
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); // 16 数组名a单独放在sizeof内部,数组名表示整个数组,计算的是整个数组的大小
printf("%d\n", sizeof(a + 0));// 4 a表示首元素的地址,a+0还是首元素的地址,地址的大小是4/8个字节,
// 是地址就有32位和64位的区分
printf("%d\n", sizeof(*a)); // 4 a表示首元素的地址,*a就是首元素 ==》a[0],大小就是4个字节 *a == *(a+0) == a[0]
printf("%d\n", sizeof(a + 1));// 4 a表示首元素的地址,a+1是第二个元素的地址,大小是4/8个字节
printf("%d\n", sizeof(a[1])); // 4 a[1]就是第二个元素,所以大小是4个字节
printf("%d\n", sizeof(&a)); // 4 &a代表数组的地址,4/8字节
printf("%d\n", sizeof(*&a)); // 16 &a是数组的地址,对数组的地址解引用拿到的是整个数组元素的地址
printf("%d\n", sizeof(&a + 1));// 4 &a是数组的地址,&a+1跳过整个数组地址,还是地址所以是4/8个字节
printf("%d\n", sizeof(&a[0])); // 4 &a[0])是首元素地址,所以是4/8个字节
printf("%d\n", sizeof(&a[0] + 1));// 4 &a[0] + 1第二个元素地址所以是4/8个字节
return 0;
}
第二组:
char arr[] = {'a','b','c','d','e','f'};
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));
怎么样,看得懂多少呢?
是否是你心中的答案呢?
接下来继续给大家分析。
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));// 6 arr代表整个数组,计算的是整个数组大小
printf("%d\n", sizeof(arr + 0));// 4 arr+0是首元素的地址,所以是4/8个字节
printf("%d\n", sizeof(*arr));// 1 这里的arr存放的是首元素地址,解引用拿到的是首元素,所以是1个字节
printf("%d\n", sizeof(arr[1]));// 1 arr[1]是第二个元素,所以是一个字节
printf("%d\n", sizeof(&arr));// 4 &arr是整个数组的地址,地址的4/8个字节
printf("%d\n", sizeof(&arr + 1));// 4 &arr是数组的地址,&arr+1跳过整个数组地址,还是地址所以是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));// 4 &arr[0]是首元素地址,&arr[0] + 1跳过一个元素地址,
// 所以是第二个元素地址,4/8个字节
return 0;
}
又对了多少呢?错了没关系,请看下一组。
第三组:
不急,先给大家看看输出。
报错了。为什么呢?稍等,看我分析。
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));// 随机值 系统会分配一块内存空间,然后把元素放进去,而strlen是
// 遇到一个起始地址然后往后找'\0',直到遇到'\0'才停止。
printf("%d\n", strlen(arr + 0));// 随机值 arr+0从首元素地址开始找'\0'
//printf("%d\n", strlen(*arr));// 报错error strlen识别的是地址 *arr == 'a' == 97
// strlen以为传进来的是 'a' 的acsII值97就是地址
//printf("%d\n", strlen(arr[1]));// error 'b' - 98
printf("%d\n", strlen(&arr));// 随机值 &arr也是从首元素地址开始
printf("%d\n", strlen(&arr + 1));// 随机值-6 &arr + 1跳过整个数组
printf("%d\n", strlen(&arr[0] + 1));// 随机值-1 &arr[0] + 1第二个元素地址
return 0;
}
第四组:
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));
看看完了吗?
上答案
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));// 7个字节 arr计算的是整个数组,数组包含'\0',所以是7个字节
printf("%d\n", sizeof(arr + 0));// 4 arr+0代表首元素地址,所以是4/8个字节
printf("%d\n", sizeof(*arr));// 1 *arr == a[0]表示首元素
printf("%d\n", sizeof(arr[1]));// 1 arr[1]表示第二个元素
printf("%d\n", sizeof(&arr));// 4 &arr代表整个数组地址,地址是4/8个字节
printf("%d\n", sizeof(&arr + 1));// 4 &arr+1表示跳过arr整个数组的地址,地址是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));// 4 &a[0] + 1第二个元素地址所以是4/8个字节
return 0;
}
第五组:
int main()
{
char arr[] = "abcdef";
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));
return 0;
}
废话不多说,上答案
int main()
{
char arr[] = "abcdef";
// [ a b c d e f \0 ]
printf("%d\n", strlen(arr));// 6 从arr首元素起始位置直到'\0'计算有6个元素
printf("%d\n", strlen(arr + 0));// 6 同上
//printf("%d\n", strlen(*arr)); 报错error strlen识别的是地址 *arr == 'a' == 97
// strlen以为传进来的是 'a' 的acsII值97就是地址
//printf("%d\n", strlen(arr[1])); error 'b' - 98
printf("%d\n", strlen(&arr));// 6 同strlen(arr)
printf("%d\n", strlen(&arr + 1));// 随机值 &arr + 1跳过整个数组,起始位置在arr之后
printf("%d\n", strlen(&arr[0] + 1));// 5 &arr[0] + 1表示第二个元素地址,其实位置在第二个元素,所以是5个
return 0;
}
第六组:
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));
return 0;
}
上答案
接下来,继续解析
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));// 4 p是指针变量,是地址所以是4/8个字节
printf("%d\n", sizeof(p + 1));// 4 p是首元素地址p+1是第二个元素地址 4/8
printf("%d\n", sizeof(*p));// 1 p是首元素地址解引用拿到的是'a'
printf("%d\n", sizeof(p[0]));// 1 p[0]是首元素拿到的是'a'
printf("%d\n", sizeof(&p));// 4 &p是地址,所以是4/8个字节
printf("%d\n", sizeof(&p + 1));// 4 &p+1跳过指针p的地址 4/8
printf("%d\n", sizeof(&p[0] + 1));// 4 &p[0]是首元素地址+1跳过一个元素地址 地址4/8
return 0;
}
第七组:
int main()
{
char* p = "abcdef";
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));
return 0;
}
到这里是不是都会做了
接下来继续上答案
int main()
{
char* p = "abcdef";
// [ a b c d e f \0 ]
printf("%d\n", strlen(p));// 6 指针变量p存放首元素地址,从a地址处到'\0'有6个元素
printf("%d\n", strlen(p + 1));// 5 p+1是第二个元素地址
//printf("%d\n", strlen(*p)); err p[0] == *(p+0) == *p strlen识别的是地址
// // strlen以为传进来的是 'a' 的acsii值97就是地址
//printf("%d\n", strlen(p[0])); err 同上
printf("%d\n", strlen(&p));// 随机值 &p从指针p变量地址开始找'\0'
printf("%d\n", strlen(&p + 1));// 随机值 &p+1跳过&p找到p下一个地址找'\0'
printf("%d\n", strlen(&p[0] + 1));// 5 &p[0] + 1是第二个元素地址找'\0'
return 0;
}
是不是有点难度
下一组难度更大
第八组:
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));
printf("%d\n", sizeof(a[3]));
return 0;
}
先看看
那么你做对了几道呢?
int main()
{
//数组名a没有单独放在sizeof内部,也没有取地址(&a),则代表的是首元素(第一行)的地址
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));// 48 数组a代表整个数组,所以计算整个数组大小
printf("%d\n", sizeof(a[0][0]));// 4 a[0][0]表示首元素
printf("%d\n", sizeof(a[0]));// 16 a[0] 代表第一行的所有元素
printf("%d\n", sizeof(a[0] + 1));// 4 a[0]是第一行数组的数组名代表第一行第一个元素地址+1则是第一行第
// 二个元素的地址,是地址所以是4/8个字节
printf("%d\n", sizeof(*(a[0] + 1)));// 4 a[0]代表第一行第一个元素地址+1则是第一行第二个元素的地址,
// 解引用则是4个字节
printf("%d\n", sizeof(a + 1));// 4 二维数组的数组名代表的是第一行的地址+1跳过第一行,代表第二行地址
// 所以是4/8
printf("%d\n", sizeof(*(a + 1)));// 16 二维数组的数组名代表的是第一行的地址+1跳过第一行,代表第二行地址
// 解引用拿到第二行的所有元素
printf("%d\n", sizeof(&a[0] + 1));// 4 &a[0]是第一行地址+1则是第二行地址,地址是4/8
printf("%d\n", sizeof(*(&a[0] + 1)));// 16 &a[0]是第一行地址+1则是第二行地址,解引用拿到第二行的所有元素
printf("%d\n", sizeof(*a));// 16 a代表首元素地址(第一行),解引用则拿到第一行的所有元素
printf("%d\n", sizeof(a[3]));// 16 a[3]假设存在,就是第四行的数组名,sizeof(a[3])就
// 相当于拿数组名单独放在sizeof内
return 0;
}
今天的分享就到这了,喜欢的话就一键三连吧,谢谢。