深度剖析指针(下)——“C”

简介: 深度剖析指针(下)——“C”

各位CSDN的uu们你们好呀,今天小雅兰的内容还是我们的指针呀,上两篇博客我们基本上已经把知识点过了一遍,这篇博客就让小雅兰来带大家看一些和指针有关的题目吧,现在,就让我们进入指针的世界吧


复习:


数组和指针


数组——能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型


指针——地址/指针变量,大小是4or8个字节


数组是数组,指针是指针,二者不等价


数组名是数组首元素的地址,这个地址就可以存放在指针变量中


可以使用指针来遍历数组


数组名


大部分情况下数组名是数组首元素的地址


但是有两个例外:


sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小

&数组名——数组名表示整个数组,取出的是数组的地址  

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    //一维数组
  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));
}

11a43a4c22d0465090487bdae0e3c3ab.png

   int a[] = { 1,2,3,4 };

   printf("%d\n", sizeof(a));//16

   //sizeof(a)就是数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节



   printf("%d\n", sizeof(a + 0));//4or8个字节

   //a+0 其实是数组首元素的地址



   printf("%d\n", sizeof(*a));//4

   //a是数组首元素的地址——&a[0]

   //*a-*&a[0]-a[0]

   //那么就是一个整形元素的大小,就是4个字节



   printf("%d\n", sizeof(a + 1));//4or8

   //a是数组首元素的地址-&a[0] int *

   //a+1 表示跳过一个整型,是第二个元素的地址



   printf("%d\n", sizeof(a[1]));//4

   //数组第二个元素



   printf("%d\n", sizeof(&a));//4or8

   //&a-取出的是数组的地址,但是数组的地址也是地址啊,是地址,大小就是4or8个字节

   //int (*pa)[4]=&a;——数组指针



   printf("%d\n", sizeof(*&a));//16

   //*操作符和&操作符互相抵消,结果就是sizeof(a)



   printf("%d\n", sizeof(&a + 1));//4or8

   //&a-取出整个数组的地址 int (*)[4]

   //&a+1-跳过一个数组



   printf("%d\n", sizeof(&a[0]));//4or8

   //取出首元素的地址



   printf("%d\n", sizeof(&a[0] + 1));//4or8

   //第二个元素的地址  

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    //字符数组
  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));
  return 0;
}

c3acbb61681f43d3942f21bbaa5ab571.png

sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么

sizeof不是函数,是操作符

strlen是函数

strlen是针对字符串的,求的是字符串的长度,本质上统计的是\0之前出现的字符

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

   printf("%d\n", sizeof(arr));//6

   //数组的总大小



   printf("%d\n", sizeof(arr + 0));//4or8

   //数组名是首元素的地址

   //arr+0 表示数组首元素的地址



   printf("%d\n", sizeof(*arr));//1

   //数组名表示数组首元素的地址-&arr[0]

   //*arr就是数组的第一个元素,就是求首元素的大小



   printf("%d\n", sizeof(arr[1]));//1

   //数组的第二个元素



   printf("%d\n", sizeof(&arr));//4or8

   //&arr取出的是整个数组的地址



   printf("%d\n", sizeof(&arr + 1));//4or8

   //&arr+1-跳过一个数组



   printf("%d\n", sizeof(&arr[0] + 1));//4or8

   //数组第二个元素的地址

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
    //字符数组
  char arr[] = { 'a','b','c','d','e','f' };
  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;
}

fbad098348114b25b39e5ff5aca2bfc3.png

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

   printf("%d\n", strlen(arr));//随机值



   printf("%d\n", strlen(arr + 0));//随机值



   printf("%d\n", strlen(*arr));//err

   //*arr就表示字符a,字符a的ASCII码值是97

   //就是说,把内存为97的地址访问了,这是一个非法访问



   printf("%d\n", strlen(arr[1]));//err

   //字符b的ASCII码值为98,把98当成了地址

   //又非法访问了



   printf("%d\n", strlen(&arr));//随机值

   //取出的是整个数组的地址



   printf("%d\n", strlen(&arr + 1));//随机值

   //&arr+1-跳过一个数组

   //这个随机值和上面的随机值比起来,应该是:随机值-6



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

   //从字符b往后数,还是一个随机值

   //这个随机值和上面的随机值比起来,应该是:随机值-1

756d2dff6ec341e8a136bd62ef790732.png

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    char arr[] = "abcdef";//a b c d e f \0
  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));
  return 0;
}

1ff57e7701f84fdd9203b19a33743e2a.png

   char arr[] = "abcdef";

   //a b c d e f \0

   printf("%d\n", sizeof(arr));//7

   //计算的是数组总元素的大小,\0也算



   printf("%d\n", sizeof(arr + 0));//4or8

   //计算的是数组首元素的地址



   printf("%d\n", sizeof(*arr));//1

   //*arr就是数组首元素,计算的是第一个元素的大小

   //arr[0]——*(arr+0)

   //求元素个数

   //int sz=sizeof(arr)/sizeof(arr[0]);

   //int sz=sizeof(arr)/sizeof(*arr);



   printf("%d\n", sizeof(arr[1]));//1

   //计算的是数组第二个元素的大小



   printf("%d\n", sizeof(&arr));//4or8

   //取出的是整个数组的地址,是地址就是4个或者8个字节



   printf("%d\n", sizeof(&arr + 1));//4or8

   //跳过一个数组,但还是地址



   printf("%d\n", sizeof(&arr[0] + 1));//4or8

   //数组第二个元素的地址

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
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;
}

char arr[] = "abcdef";

   //a b c d e f \0

   printf("%d\n", strlen(arr));//6

   //找\0



   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

   //&arr-char (*)[7]

   //也是数到\0就停止了



   printf("%d\n", strlen(&arr + 1));//随机值



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

   //从数组第二个元素开始数,数到\0

f125a5f843e84735b8f89088358bec13.png

4fc8e59ab4724638ac8991d49ed63a35.png

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
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;
}

char* p = "abcdef";

   //把首字符a的地址放在p变量中,p是一个指针变量



   printf("%d\n", sizeof(p));//4or8

   //计算的是指针变量的大小,也就是计算a的地址的大小



   printf("%d\n", sizeof(p + 1));//4or8

   //计算的是字符b的地址的大小



   printf("%d\n", sizeof(*p));//1

   //p是一个指针变量,里面存放的是a的地址

   //p解引用之后就是元素a,字符a的大小是一个字节



   printf("%d\n", sizeof(p[0]));//1

   //可以把p[0]理解为*(p+0)

   //也就是字符a,字符a的大小是1个字节



   printf("%d\n", sizeof(&p));//4or8

   //取出的是p的地址



   printf("%d\n", sizeof(&p + 1));//4or8

   //p-char *

   //&p-char **

   //char * p;

   //char * *pp=&p;

   //&p+1跳过一个char*的元素

   //反正还是地址



   printf("%d\n", sizeof(&p[0] + 1));//4or8

   //第二个元素的地址

cd6181eacd184c43a05bcdf103455a6f.png

d5042488c6fa4a19a27d5a555b03c66d.png

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
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;
}

 char* p = "abcdef";

   printf("%d\n", strlen(p));//6

   //p是a的地址



   printf("%d\n", strlen(p + 1));//5

   //p+1是b的地址



   printf("%d\n", strlen(*p));//err

   //字符a 非法访问了



   printf("%d\n", strlen(p[0]));//err

   //字符a 非法访问了



   printf("%d\n", strlen(&p));//随机值

   //a的地址的地址,什么时候遇到\0完全是不可知的



   printf("%d\n", strlen(&p + 1));//随机值

   //跳过p变量

   //这两个随机值是没有关系的



   printf("%d\n", strlen(&p[0] + 1));//5

   //从字符b往后数,数到\0

c3c5d553bacd44f4be598f4fc8e6ebe5.png

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
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;
}

deb796ee3a0a4a1eae853e02e9f6b4cd.png

 int a[3][4] = { 0 };

   printf("%d\n", sizeof(a));//48——3*4*4

   //a这个二维数组的数组名单独放在sizeof内部,计算的是二维数组的总大小



   printf("%d\n", sizeof(a[0][0]));//4

   //第一行第一个元素



   printf("%d\n", sizeof(a[0]));//16

   //a[0]是第一行的数组名,这时数组名单独放在sizeof内部了

   //计算的是数组的大小,单位是字节

   //计算的是第一行的大小



   printf("%d\n", sizeof(a[0] + 1));//4or8

   //a[0]不是单独放在sizeof内部,a[0]表示首元素的地址

   //也就是第一行第一个元素的地址,即&a[0][0]

   //那么,a[0]+1就是第一行第二个元素的地址,也就是&a[0][1]



   printf("%d\n", sizeof(*(a[0] + 1)));//4

   //第一行第二个元素



   printf("%d\n", sizeof(a + 1));//4or8

   //a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址

   //二维数组的首元素是第一行,这里的a就是第一行的地址——int (*)[4]

   //a+1是跳过第一行,指向了第二行

   //所以是第二行的地址



   printf("%d\n", sizeof(*(a + 1)));//16

   //第二行的元素得大小 4*4

   //*(a+1)——a[1]



   printf("%d\n", sizeof(&a[0] + 1));//4or8

   //取出第一行的地址,&a[0]+1是第二行的地址



   printf("%d\n", sizeof(*(&a[0] + 1)));//16

   //第二行的元素的大小



   printf("%d\n", sizeof(*a));//16

   //*a 数组名表示首元素的地址,a就表示二维数组第一行的地址

   //解引用就是第一行的元素



   printf("%d\n", sizeof(a[3]));//16

   //第四行的数组名

   //不存在越界

   //因为,sizeof内部的表达式不会真的计算

   //所以,编译器压根不会去访问第四行,而是直接根据类型属性判断

a12884e3e8794d6f90e670c116a60cd3.png

a86bf3c23eed4e54a2908902bf3cf011.png

好啦,小雅兰今天的内容就到这里啦,指针系列的博客真的花了小雅兰超级多的时间,未来还要继续加油呀!!!

70089e3e90f24f25b114e1670bf211c3.jpg


相关文章
|
存储 算法 C语言
C语言深度剖析指针
C语言深度剖析指针
64 0
|
存储 C语言 C++
深度剖析C语言指针笔试题 Ⅱ
&lt;1&gt;主页:C语言的前男友 &lt;2&gt;知识讲解:C语言指针 &lt;3&gt;创作者:C语言的前男友 &lt;4&gt;开发环境:VS2022 &lt;5&gt;前言:继续练习指针的笔试题,今天的笔试题更有难度哦。欢迎大家前来指正,如果觉得作者写的还不错的话,请麻烦动动发财的小手,关注,点赞,收藏,评论。
|
存储
学C的第二十三天【继续深度剖析数据在内存中的存储:3. 浮点型在内存中的存储(重点);练习:1. 有序序列判断;2. 获得月份天数(多组输入);3. 使用指针打印数组内容;4. 使用指针使字符串逆序】-2
(4). 取出内存中的 指数E(三种情况):E全为1 指数E 是通过 真实值+中间值 算出来的,如果E全是1,(32位系统)说明E的真实值是 128,指数是128说明这个值是非常大的。 这时,如果 有效数字M 全为0,表示 ±无穷大(正负取决于符号位s)
|
存储 C语言 C++
深度剖析指针(上)——“C”
深度剖析指针(上)——“C”
|
C语言 索引
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表2
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表
93 0
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表2
|
机器学习/深度学习 存储 索引
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表
125 0
【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 && 复制带随机指针的链表
|
存储 C语言
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)(续)
浮点数在内存中存储,并不想我们想的是完整存储的 在十进制转化成为二进制,是有可能有精度损失的
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)(续)