指针和数组笔试题解析

目录

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]));

解析如下:

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

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

二维数组可以理解为一维数组的数组,a[0]相当于第一行数组的数组名

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;
}

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

相关推荐
liujjjiyun13 分钟前
小R的随机播放顺序
数据结构·c++·算法
¥ 多多¥23 分钟前
c++中mystring运算符重载
开发语言·c++·算法
trueEve1 小时前
SQL,力扣题目1369,获取最近第二次的活动
算法·leetcode·职场和发展
天若有情6731 小时前
c++框架设计展示---提高开发效率!
java·c++·算法
ahadee1 小时前
蓝桥杯每日真题 - 第19天
c语言·vscode·算法·蓝桥杯
Theliars2 小时前
C语言之字符串
c语言·开发语言
Reese_Cool2 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
加密新世界2 小时前
优化 Solana 程序
人工智能·算法·计算机视觉
不爱说话郭德纲3 小时前
探索LLM前沿,共话科技未来
人工智能·算法·llm
搬砖的小码农_Sky3 小时前
C语言:结构体
c语言·数据结构