指针和数组笔试题解析

目录

1.一维数组

2.字符数组

[2.1 char arr\[\] = {'a','b','c','d','e','f'}](#2.1 char arr[] = {'a','b','c','d','e','f'})

[2.2 char arr\[\] = "abcdef"](#2.2 char arr[] = "abcdef")

[2.3 char *p = "abcdef"](#2.3 char *p = "abcdef")

3.二维数组


全面分析指针和数组笔试题,带你加深了解数组和指针,努力学习,加油!

1.一维数组

cpp 复制代码
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));

int a\[\] = {1,2,3,4}; 一维数组四个元素,每个元素是int 类型(四个字节)

  1. int数组sizeof(数组名)计算整个数组的大小,答案为16
  2. int数组sizeof(数组名+其他)此处数组名并未单独放在sizeof内部,为数组首元素地址,答案为4或8
  3. 数组名为数组首元素地址,解引用后指向数组第一个元素 '1' ,答案为4
  4. int型指针+1跳过四个字节,地址(指针)加1或者-1仍然是地址(指针),答案为4或8
  5. 数组第二个元素的大小,答案为4
  6. &a意义是整个数组的地址,但是整个数组的地址仍然是个指针,因此指针大小还是4或8
  7. 此处可以理解为&符号和*符号相互抵消,等价于sizeof(数组名),为整个数组的大小,答案为16
  8. &a+1跳过整个数组,但是仍然是地址,地址取决于编译环境,答案为4或8
  9. 数组首元素的地址,答案为4或8
  10. 数组首元素地址+1,跳过四个字节指向第二个元素,但仍然是地址,答案为4或8

2.字符数组

2.1char arr\[\] = {'a','b','c','d','e','f'}

cpp 复制代码
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));
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));

解析如下:

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

int main()
{

	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", sizeof(arr));//字符数组,数组名为首元素地址,但是单独放在sizeof()内部为整个数组大小,打印6
	printf("%zd\n", sizeof(arr + 0));//数组名为首元素地址,并未&并且并未单独放在sizeof内部,地址的大小,4或者8
	printf("%zd\n", sizeof(*arr));//数组名为首元素地址  *arr为数组第一个元素'a',打印第一个元素大小,打印1
	printf("%zd\n", sizeof(arr[1]));//打印数组第二个元素的大小,为1
	printf("%zd\n", sizeof(&arr));//地址的大小,为4或者8
	printf("%zd\n", sizeof(&arr + 1));//地址的大小。为4或者8
	printf("%zd\n", sizeof(&arr[0] + 1));//地址的大小,为4或者8


	printf("%zd\n", strlen(arr));//计算字符串长度,从数组首元素开始计算,但是字符串中并未有结束符" \0 ",因此为随机值
	printf("%zd\n", strlen(arr + 0));//计算字符串长度,从数组首元素开始计算,但是字符串中并未有结束符" \0 ",因此为随机值
	printf("%zd\n", strlen(*arr));//站在strlen角度认为    将字符'a'---97当作字符串起始地址,非法地址,访问错误
	printf("%zd\n", strlen(arr[1]));//站在strlen角度认为  将字符'b'---98当作字符串起始地址,非法地址,访问错误
	printf("%zd\n", strlen(&arr));//&arr类型为 char (*)[6]  传入strlen会进行转化为const char*,因此还是从数组首元素开始计算长度,为随机值
	printf("%zd\n", strlen(&arr + 1));//&arr+1跳过一个数组后往后数,仍然为随机值,
	printf("%zd\n", strlen(&arr[0] + 1));//&arr[0]+1跳过一个字符后往后数,但仍然为随机值

	return 0;
}

2.2 char arr\[\] = "abcdef"

cpp 复制代码
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));

解析如下:

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	//arr数组中实际有"abcdef\0"
	printf("%d\n", sizeof(arr));//sizeof(数组名)计算整个数组大小,包括了\0,答案为7
	printf("%d\n", sizeof(arr + 0));//sizeof(首元素地址+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));//计算\0之前的字符个数,为6
	printf("%d\n", strlen(arr + 0));//答案为6
	printf("%d\n", strlen(*arr));//strlen认为字符'a'---97为字符起始地址,非法访问,错误
	printf("%d\n", strlen(arr[1]));//strlen认为字符'b'---98为字符起始地址,非法访问,错误
	printf("%d\n", strlen(&arr));//&arr类型为--char (*)[6] 传入strlen函数会被转化为const char *,因此从首元素位置开始向后计数。为6
	printf("%d\n", strlen(&arr + 1));//&arr类型为---char (*)[6]  +1 后跳过一个数组大小,为随机值
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0]类型为---char * +1跳过一个字符指针大小,答案为5


	return 0;
}

2.3 char *p = "abcdef"

cpp 复制代码
    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));

解析如下:

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char* p = "abcdef";//字符指针,将字符串首位置字符'a'的地址传给 p

	printf("%zd\n", sizeof(p));//计算字符指针p的大小,4或者8
	printf("%zd\n", sizeof(p + 1));//计算指针的大小,4或者8
	printf("%zd\n", sizeof(*p));//计算字符'a'的大小,为1
	printf("%zd\n", sizeof(p[0]));//计算字符'a'的大小,为1,可以理解为p[0]--> *(p+0)
	printf("%zd\n", sizeof(&p));//计算指针的大小,4或者8
	printf("%zd\n", sizeof(&p + 1));//计算指针的大小,4或者8
	printf("%zd\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));//*p指向a,将字符'a'---97看作起始地址,非法访问,错误
	printf("%d\n", strlen(p[0]));//同样是将字符'a'---97看作起始地址,非法访问,错误
	printf("%d\n", strlen(&p));//&p为二级指针,该地址中的字符未知,所以是随机值
	printf("%d\n", strlen(&p + 1));//跳过了该数组,后续未知,所以为随机值
	printf("%d\n", strlen(&p[0] + 1));//字符串首元素地址+1后指向字符'b',计算长度为5

	return 0;
}

3.二维数组

cpp 复制代码
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]));

解析如下:

我们可以将二维数组存储看作如下图:

但是二维数组在内存中真实情况是连续存放的

二维数组可以理解为一维数组的数组,a0相当于第一行数组的数组名

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int a[3][4] = { 0 };
	//
	printf("%d\n", sizeof(a));//二维数组 a 也是数组名,数组名单独放在sizeof内部,表示整个数组,计算整个数组的大小,为3*4*4 =48
	printf("%d\n", sizeof(a[0][0]));//计算a[0][0]元素大小,为4
	printf("%d\n", sizeof(a[0]));//,二维数组可以理解为一维数组的数组,a[0]相当于第一行数组的数组名,单独放在sizeof内部,计算的是整个第一行数组的大小,为4*4 =16
	printf("%d\n", sizeof(a[0] + 1));//a[0]并没有单独放在sizeof内部,也没有&,所以代表第一行第一个元素的地址,相当于a[0]-->&a[0][0],计算的是第一行第二个元素的地址的大小为4或者8
	printf("%d\n", sizeof(*(a[0] + 1)));//代表计算第一行第二个元素的大小,int类型大小为4
	printf("%d\n", sizeof(a + 1));//地址的大小,4或者8,a作为二维数组数组名并没有单独放在siezof内部,也没有&,所以a表示数组首元素地址,也就是第一行的地址,第一行的地址+1为第二行的地址
	printf("%d\n", sizeof(*(a + 1)));//解引用第二行数组的地址拿到整个第二行数组,大小为16
	printf("%d\n", sizeof(&a[0] + 1));//计算第一行第二个元素的地址,4或者8
	printf("%d\n", sizeof(*(&a[0] + 1)));//a[0]是第一行的数组名,&a[0]取出的是第一行的一维数组的地址,+1后为第二行的地址,解引用访问第二行,大小为16
	printf("%d\n", sizeof(*a));//a表示数组首元素地址,也就是第一行的地址,*a对第一行解引用,计算第一行数组大小为16
	printf("%d\n", sizeof(a[3]));//虽然不存在a[3],但不会越界,因为sizeof运算并不会真的在内存中去访问该数组,所以仍然能计算出大小为16,相当于编译器已经确定了类型a[0]--int [4] a[3]--int [4]
	//表达式有两个属性,一个是值属性,一个是类型属性
	return 0;
}

谢谢大家的支持与鼓励!下次再见!

相关推荐
冻柠檬飞冰走茶18 分钟前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
雪落漂泊38 分钟前
C++算法 二分查找篇(上)
开发语言·c++·算法
LabVIEW开发2 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
严肃小白兔4 小时前
MATLAB 数值计算中的精度与误差问题:浮点运算、误差传播与数值稳定性
人工智能·算法·matlab
Hhy_11074 小时前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
青少儿编程课堂5 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
jktantan6 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
曦樂~16 小时前
Cpp面筋
c语言·c++
Dream it possible!18 小时前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
心抵鹊19 小时前
算法之双指针系列(一)
算法·leetcode