指针进阶-->笔试题详解(数组笔试题)

简介: 指针进阶-->笔试题详解(数组笔试题)

💕"痛苦难以避免,而磨难可以选择。"-->村上春树💕

作者:Mylvzi

文章主要内容:数据在内存中的存储

核心知识点:

核心:

1.对于数组名的理解:数组名是数组首元素的地址(二维数组的数组名就是第一行的地址),但有两个例外,一是单独出现在sizeof内部,表示整个数组的大小,二是&数组名,代表存放整个数组的地址;

2.理解sizeof只关注()的数组类型,是地址,大小就为4/8;关注()的数据类型(数组的数据类型就是去掉数组名)

3.理解指针变量存储字符串的本质-->存储字符串首元素的地址

4.理解二维数组的元素构成,即二维数组是一维数组的数组;

5.理解数组与指针之间的的等价关系;arr[1]-->*(arr+1)  *arr-->*(arr+0)-->arr[0]

6.理解strlen函数的本质即参数类型,本质是计算\0之前的字符个数,参数是const char*,是一个地址,也就是说strlen是从你传的地址作为首地址,一直向后读取字符个数,直到遇到\0;当()是元素时,会从其对应的ascii码值所在的地址访问,造成非法访问,报错

相关代码代码如下:

int main()
{
  /*一维数组*/
  //数组名代表数组首元素地址,但有两个例外
  //1.sizeof数组名,计算的是整个数组的大小(数组名单独放在sizeof内部)
  //2.&数组名,代表整个数组的地址
  //sizeof 只关注类型,要分清代表的是元素还是地址
  //对于指针,我们要关注他的指向,也就是存放的地址;其大小是固定的
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));//16 ->int [4]
  printf("%d\n", sizeof(a + 0));//这里的a是数组首元素的地址,+0还是数组首元素的地址,大小为4/8byte
  printf("%d\n", sizeof(*a));//数组首元素,是元素,4(int类型)
  printf("%d\n", sizeof(a + 1));//第二个元素的地址,是地址,大小为4/8byte
  printf("%d\n", sizeof(a[1]));//第二个元素,是元素,大小为4
  printf("%d\n", sizeof(&a));//&a也是地址,是地址,4/8byte
  printf("%d\n", sizeof(*&a));//16  等价于sizeof(a)
  //&a 是数组的地址,是一个数组指针变量,类型为int(*)[4],解引用就是访问4个int类型的元素
  printf("%d\n", sizeof(&a + 1));//地址,大小为4/8byte
  printf("%d\n", sizeof(&a[0]));//地址,大小为4/8byte
  printf("%d\n", sizeof(&a[0] + 1));//地址,大小为4/8byte
  /*字符数组*/
  /*char arr[] = { 'a','b','c','d','e','f' };*/
  printf("%d\n", sizeof(arr));//数组名在sizeof内部,计算整个数组的大小,6
  printf("%d\n", sizeof(arr + 0));//是地址,大小为4/8
  printf("%d\n", sizeof(*arr));//代表字符a,大小为1
  printf("%d\n", sizeof(arr[1]));//代表字符b,大小为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
  //strlen的参数是const char* ,计算的是\0之前的字符个数
  printf("%d\n", strlen(arr));//随机值
  printf("%d\n", strlen(arr + 0));//随机值
  printf("%d\n", strlen(*arr));//err strlen的参数是一个指针,是地址,*arr,相当于将a的地址传了过去,以97为起始地址,属于非法访问内存
  printf("%d\n", strlen(arr[1]));//err 同上
  printf("%d\n", strlen(&arr));//随机值  &arr的值和arr的值是一样的,都指向数组首元素地址
  printf("%d\n", strlen(&arr + 1));//随机值  数组最后一个元素的下一位的地址
  printf("%d\n", strlen(&arr[0] + 1));//随机值 从数组第二个元素开始打印字符串
  //sizeof只关注类型,传arr是数组,数组的类型是去掉数组名
  // 对于sizeof来说,只需注意他是地址还是普通元素
  char arr[] = "abcdef"; //a b c d e f \0 
  printf("%d\n", sizeof(arr));//数组类型:char [7]; -->7
  printf("%d\n", sizeof(arr + 0));//4  地址
  printf("%d\n", sizeof(*arr));//1
  printf("%d\n", sizeof(arr[1]));//1
  printf("%d\n", sizeof(&arr));//4  本质是一个地址
  printf("%d\n", sizeof(&arr + 1));//4  地址
  printf("%d\n", sizeof(&arr[0] + 1));//4  地址
  printf("%d\n", strlen(arr));//6
  printf("%d\n", strlen(arr + 0));//6
  printf("%d\n", strlen(*arr));//非法访问内存
  printf("%d\n", strlen(arr[1]));//同上
  printf("%d\n", strlen(&arr));//6
  printf("%d\n", strlen(&arr + 1));//随机值
  printf("%d\n", strlen(&arr[0] + 1));//5
  //利用字符指针存储字符串-->指针内存储的是字符串首字符的地址
  const char* p = "abcdef";
  printf("%d\n", sizeof(p));//4  地址
  printf("%d\n", sizeof(p + 1));//4  地址
  printf("%d\n", sizeof(*p));//1  元素
  printf("%d\n", sizeof(p[0]));//p[0]->*(p+0)->*p  1
  printf("%d\n", sizeof(&p));//&p->char**  4
  printf("%d\n", sizeof(&p + 1));//&p,char**,+1,注意此处的指针变量与数组无关
  //存储的是P本身的地址  4
  printf("%d\n", sizeof(&p[0] + 1));//4 -->b的地址
  printf("%d\n", strlen(p));//6
  printf("%d\n", strlen(p + 1));//5
  printf("%d\n", strlen(*p));//err
  printf("%d\n", strlen(p[0]));//err
  printf("%d\n", strlen(&p));//随机值
  printf("%d\n", strlen(&p + 1));//随机值
  printf("%d\n", strlen(&p[0] + 1));//5
  /*二维数组*/
  //学会数组中的等价关系
  // 给定arr是数组名(一维,二维皆可)
  //arr[1]-->*(arr+1) 
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//计算整个数组的大小,3*4*4  48
  printf("%d\n", sizeof(a[0][0]));//4
  printf("%d\n", sizeof(a[0]));//4*4=16  a[0]是一个一维数组的地址,类型为int(*)[4]
  //a[0]是第一行一维数组的数组名,单独出现在sizeof内部,计算整个一维数组的大小
  printf("%d\n", sizeof(a[0] + 1));//4  a[0]是第一行一维数组的数组名,没有单独出现在sizeof内部
  //所以代表第一行一维数组的首元素的地址-->a[0][0]
  //a[0][0]+1 就是a[0][1]的地址,是一个指针变量;一定要注意指针指向
  printf("%d\n", sizeof(*(a[0] + 1)));//4  计算的就是第一行第二个元素的大小
  printf("%d\n", sizeof(a + 1));//4  
  //a是二维数组名,是第一行的地址,存的时候是通过数组指针存放的int(*)[4]
  //a+1是第二行的地址,是一个指针变量
  printf("%d\n", sizeof(*(a + 1)));//16   
  //*(a+1)-->a[1]  sizeof(*(a+1))-->sizeof(a[1]) int[4]
  printf("%d\n", sizeof(&a[0] + 1));//4 是第二行一维数组的地址,本质是一个地址
  //&a[0]是第一行的地址
  printf("%d\n", sizeof(*(&a[0] + 1)));//16  是对第二行整个一维数组解引用
  //计算第二行整个一维数组的大小
  printf("%d\n", sizeof(*a));//16  a是二维数组数组名,代表二维数组第一行的地址
  //*a就是对第一行解引用,计算第一行整个一维数组的大小
  //*a-->*(a+0)-->a[0]-->sizeof(a[0])
  printf("%d\n", sizeof(a[3]));//16-->a[3]是一个一维数组,数组类型为int[4]
  //sizeof只关注()内的数据类型,只关注类型属性
  //表达式有两个属性
  //1.值属性:即表达式最后的计算结果
  //2.类型属性:即表达式计算结果的类型
  int a = 7;
  short s = 4; 
  printf("%d\n", sizeof(s = a + 2));//short 2
  printf("%d\n", s);//4
  return 0;
}


目录
相关文章
|
20天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
30 3
|
19天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
30 2
|
28天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
31 1
|
1月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
1月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
19 0
|
1月前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
|
3月前
|
搜索推荐 C语言
指针与数组
指针与数组
59 9
下一篇
无影云桌面