指针和数组笔试题解析:涉及strlen与sizeof的多组详细辨析

发布于:2022-12-13 ⋅ 阅读:(479) ⋅ 点赞:(0)

指针和数组笔试题解析:涉及strlen与sizeof的多组详细辨析

1. 一维数组

关于数组名:

数组名是数组首元素的地址, 但是, 有两个例外:

  1. sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2. &数组名 - 数组名也表示整个数组,取出的是整个数组的地址
  3. 除了这两个例外,见到的所有数组名都表示首元素的地址
int main()
{
	int a[] = { 1,2,3,4 };
	int* p = a;
	int(*p)[4] = &a;
	//差4
	p;
	p + 1;
	//相等
	pa;
	pa + 1;

	//a  - int*
	//&a - int(*)[4]
	printf("%d\n", sizeof(a));//16,a作为数组名单独存放在sizeof内部,计算的是数组的总大小,单位是字节
	printf("%d\n", sizeof(a + 0));//a并非单独存放在sizeof内部,也没有&,所以数组名a就是首元素的地址
	//a+0还是数组首元素的地址,是地址大小就是4/8个字节
	printf("%d\n", sizeof(*a));//a是首元素的地址,*a就是首元素,sizeof(*a)算的就是首元素的大小 - 4
	//a - int*
	//*a - int
	printf("%d\n", sizeof(a + 1));//a是首元素的地址,a+1是第二个元素的地址,sizeof(a+1)计算的是指针的大小 - 4/8
	//a - int*
	//a+1,跳过一个int
	printf("%d\n", sizeof(a[1]));//a[1]就是数组的第二个元素,sizeof(a[1])的大小 - 4个字节
	printf("%d\n", sizeof(&a));//&a取出数组的地址,也是地址 - 4/8个字节
	printf("%d\n", sizeof(*&a));//&a是数组的地址,是是指指针类型,*&a是对数组指针解引用,访问一个数组的大小 - 16字节
	//sizeof(*&a) ==> sizeof(a) =16
	printf("%d\n", sizeof(&a + 1));//&a数组的地址,&a+1跳过整个数组,&a+1还是地址,是4/8个字节
	printf("%d\n", sizeof(&a[0]));//a[0]是数组的第一个元素,&a[0]是第一个元素的地址,是4/8个字节
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一个元素的地址,&a[0]就是第二个元素的地址,是4/8个字节
	//&a[0] - int*
	//&a[0]+1 - &a[1]
	return 0;
}

& - 取地址操作符; * - 解引用操作符

1.1 字符数组{}型

1.1.1 sizeof(arr)

  1. sizeof是计算对象或者类型创建的对象所占空间的大小,单位是字节
  2. sizeof是操作符,不是函数
    char arr[] = { 'a','b','c','d','e','f' };//6个元素
	printf("%d\n", sizeof(arr));//arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小,单位是字节 - 6
	printf("%d\n", sizeof(arr + 0));//arr是数组名,并非单独放在sizeof内部,arr表示首元素的地址
	//是地址大小就是4/8
	printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,sizeof计算的是首元素的大小 - 1字节
	printf("%d\n", sizeof(arr[1]));//arr[1]是数组的第二个元素,sizeof(arr[1])计算的是第二个元素的大小 - 1字节
	printf("%d\n", sizeof(&arr));//&arr - char(*)[6]
	//取出的是数组的地址,计算数组地址的大小,是地址就是4/8字节
	printf("%d\n", sizeof(&arr + 1));//&arr是数组的地址,&arr + 1跳过整个数组,指向'f'的后边,
	//&arr+1的本质还是地址,是地址就是4/8字节
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]是'a'的地址,&arr[0] + 1是’b'的地址也是4/8个字节

1.1.2 strlen(arr)

  1. strlen 求字符串长度的,计算的是字符串中\0之前出现的字符的个数
  2. 统计到\0为止,如果没有看到\0,会继续往后找
  3. strlen 是库函数
  4. 字符串的结束标志是’\0’,ASCII码值是0
    printf("%d\n", strlen(arr));//随机值,arr是数组名,但是没有放在sizeof内部,也没&,arr就是首元素的地址 
	//strlen得到arr后,从arr数组首元素的地方开始计算字符串的长度,直到\0,但是arr数组中没有\0,arr内存的后面是否有\0
	//在什么位置是不确定的,所以\0之前出现的字符是随机的
	printf("%d\n", strlen(arr + 0));//arr是数组首元素的地址,arr+0还是首元素的地址 - 随机值
	printf("%d\n", strlen(*arr));//arr是数组首元素的地址,*arr是首元素 - 'a' - 97
	//strlen就把'a'的ASCII码值97当成了地址
	//error 会非法访问内存
	printf("%d\n", strlen(arr[1]));//err arr[1] - 'b' - 98
	printf("%d\n", strlen(&arr));//随机值,&arr是数组的地址,数组的地址也是指向数组的起始位置,和第一个案例一样
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//随机值

1.2 字符数组“”

1.2.1 sizeof(arr)

    char arr[] = "abcdef";//7
	printf("%d\n", sizeof(arr));//4/8
	printf("%d\n", sizeof(arr + 0));//1
	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

1.2.2 strlen(arr)

    printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//err
	printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机
	printf("%d\n", strlen(&arr[0] + 1));//5

1.3 char*

1.3.1 sizeof ( p )

小结:*p == *(p+0) == p[0]

int arr[10];
int* p=arr;//p == arr
arr[i] --> p[i]//arr[i]能写的p[i]也能写

在这里插入图片描述

    char* p = "abcdef";
	printf("%d\n", sizeof(p));//计算一个指针变量的大小 - 0x0012ff40 - 4/8
	printf("%d\n", sizeof(p + 1));//4/8 - 0x0012ff41
	printf("%d\n", sizeof(*p));//1 - char*解引用
	printf("%d\n", sizeof(p[0]));//*p == *(p+0) == p[0] -第一个元素的大小 - 1字节
	printf("%d\n", sizeof(&p));//0x9912ff40 - 4/8
	printf("%d\n", sizeof(&p + 1));//跳过整个p - 4/8
	printf("%d\n", sizeof(&p[0] + 1));//指向b - 4/8

在这里插入图片描述

//类比:
int* p2;
// p2+1 跳过一个int

char* p;
char* *pp=&p;
// pp+1 跳过一个char*对象

1.3.2 strlen ( p )

在这里插入图片描述

    printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//指向a - 传值97 - err
	printf("%d\n", strlen(p[0]));//指向第一个元素 - 97 - err
	printf("%d\n", strlen(&p));//如0x0012ff40 - 并不知道何时遇到\0 - 随机值
	printf("%d\n", strlen(&p + 1));//跳过&p整体 - 并不知道何时遇到\0 - 随机值
	printf("%d\n", strlen(&p[0] + 1));//指向b的地址,再向后数 - 5

2. 二维数组

二维数组也是数组,a就是数组名

2.1 sizeof

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]是一个整型元素,大小是四个字节
	printf("%d\n", sizeof(a[0]));//把二维数组的每一行看作一维数组的时候,a[0]是第一行的数组名,第一行的数组名单独放在sizeof内部
	//计算的是第一行的总大小 - 16字节
	printf("%d\n", sizeof(a[0] + 1));//a[0]虽然是第一行的数组名,但是没有单独放在sizeof内部
	//a[0]是第一行的数组名,不表示第一行整个数组,而是第一行首元素的地址,a[0]-->&a[0][0]
	//a[0] + 1,跳过一个int,是a[0][1]的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//a[0] + 1是第一行第二个元素的地址,所以*(a[0] + 1)就是a[0][1] - 4字节
	printf("%d\n", sizeof(a + 1));//a是二维数组的数组名,没有单独放在sizeof内部,也没有&,所以a就是数组首元素的地址
	//二维数组,我们把它想成一维数组,它的第一个元素就是二维数组的第一行
	//a就是第一行的地址 int(*)a[4]
	//a+1就是第一行的地址 - 4字节
	//a - &a[0]
	//a+1 - &a[1]
	//a+2 - &a[2]
	printf("%d\n", sizeof(*(a + 1)));//a + 1是第二行的地址,*(a+1)找到的就是第二行 - 16字节
	//*(a+1) --> a[1]
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0] + 1就是第二行的地址 - 4/8
	printf("%d\n", sizeof(*(&a[0] + 1)));//&a[0] + 1第二行的地址,*(&a[0] + 1)拿到第二行 - 16
	//*(&a[0] + 1)-> a[1]
	printf("%d\n", sizeof(*a));//a表示首元素的地址,就是第一行的地址 - &a【0】
	//*a -> *(a+0) -> a[0]
	//*a 拿到第一行
	printf("%d\n", sizeof(a[3]));//类型是:int [4]
	//二维数组的第四行,虽然没有第四行,但是可判断出类型是int [4]
	//任何一个表达式都有两个属性
	//2+7
	//值属性:8
	//类型属性:int
	return 0;
}

2.1.1 截断,对a[3]作出解释

int main()
{
	short num = 20;
	int a = 1;
	//sizeof内部表达式不参与运算
	printf("%d\n", sizeof(num = a + 5));//2
	//在编译期间被处理,因此只看类型 - num类型为short - 2字节
	printf("%d\n", num);//20
	return 0;
}

2.1.2 总结:

数组名的意义:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

网站公告

今日签到

点亮在社区的每一天
去签到