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

news2024/11/26 17:21:30

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

复习:

数组和指针

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

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

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

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

可以使用指针来遍历数组 

数组名

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

但是有两个例外:

  1. sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小
  2. &数组名——数组名表示整个数组,取出的是数组的地址 
#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));
}

 

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

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

    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

 

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

    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

 

 

#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
    //第二个元素的地址

 

 

#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

 

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

    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内部的表达式不会真的计算
    //所以,编译器压根不会去访问第四行,而是直接根据类型属性判断

 

 


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

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用Albumentations工具包进行图像的数据增强(以yolo数据标注格式为例)

最近在看数据增强方法时&#xff0c;看到了这个有趣的工具包&#xff0c;研究了下并以yolo数据标注格式为例写了一个示例脚本。 该工具最大的好处是会根据你使用的数据增强方法自动修改标注框信息&#xff01; import albumentations as A import cv2 import os""&…

【摄像头模块】口罩识别功能调试问题总结

文章目录一. 初始化二.程序烧录三.识别是否佩戴口罩小项目中常用到摄像头模块&#xff0c;文章内容疑问&#xff0c;可以私信交流 一. 初始化 1.初始界面为版本号&#xff0c;以及SD卡识别 如果未出现此界面&#xff0c;则可以按板子上的RST键&#xff0c;或者重新刷固件 …

C++动态规划之最长上升子序列

1 子序列与上升子序列1.1 子序列一个序列A{a1,a2,...an}中任意删除若干项&#xff0c;剩余的序列叫做A的一个子序列。例如序列A{1,3,5,4,2}&#xff0c;删除其中的第3项和第5项&#xff0c;得到序列B{1,3,4}&#xff0c;删除其中的第3项和第4项&#xff0c;得到序列C{1&#xf…

详述java的设计模式(三)

1.装饰者模式 装饰者模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装。 使用场景&#xff1a; 在不影响其他对象的情况下&#xff…

使用Python免费试用最新Openai API

一、背景介绍 3月2日凌晨&#xff0c;OpenAI放出了真正的ChatGPT API&#xff0c;不是背后的GPT-3.5大模型&#xff0c;是ChatGPT的本体模型&#xff01;ChatGPT API价格为1k tokens/$0.002&#xff0c;等于每输出100万个单词&#xff0c;价格才2.7美金&#xff08;约18元人民…

数据可视化展示:打工人常见职业病,颈腰椎病占比最高达66.51%

身体健康才是一切的根本。只有身体健健康康才能更好的去享受世间的美好&#xff0c;无论是谁都应当注重身体健康&#xff0c;而不是无度的挥霍它&#xff01; 良好的身体&#xff0c;释放给工作&#xff0c;健壮的体魄&#xff0c;享受美好生活&#xff0c;良好的心态&#xff…

2023年独立站建站平台有哪些?

在当今互联网时代&#xff0c;网站已经成为了人们展示自我、宣传企业、交流信息的重要平台。如果您想要打造自己的网站&#xff0c;但是没有足够的技术和设计经验&#xff0c;那么独立站建站平台可能是一个不错的选择。下面介绍一些常见的独立站建站平台。 WordPress&#xff…

活动回顾(PPT+视频)|全球人工智能开发者先锋大会 Jina AI 的现场直击!

2 月 25 - 26 日&#xff0c;全球人工智能开发者先锋大会&#xff08;GAIDC&#xff09;在上海临港中心成功举办&#xff0c;Jina AI 的高级算法工程师参加「 AI 工程化 MLOps 论坛」为大家带来精彩的主题演讲《多模态 AI 应用开发新范式》&#xff0c;开源集市迎来近 500 位小…

Python机器学习实战(一)

文章目录基于逻辑回归实现乳腺癌预测基于k-近邻算法实现鸢尾花分类基于决策树实现葡萄酒分类基于朴素贝叶斯实现垃圾短信分类基于支持向量机实现葡萄酒分类基于高斯混合模型实现鸢尾花分类基于主成分分析实现鸢尾花数据降维基于奇异值分解实现图片压缩基于逻辑回归实现乳腺癌预…

谷歌seo独立站搜索引擎优化指南【2023新版】

作为一个拥有十年操作经验的个人站长&#xff0c;我认为SEO是网站优化的核心&#xff0c;它可以帮助我们的网站在搜索引擎上获得更高的排名和更多的流量。在本篇文章中&#xff0c;我将分享我的谷歌SEO独立站搜索引擎优化指南&#xff0c;希望对您有所帮助。 一、关键词研究 关…

Invalid <url-pattern> [sso.action] in filter mapping

Tomcat 8.5.86版本启动web项目报错Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> [sso.action] in filter mapping 查看项目的web.xml文件相关片段 <filter-mapping><filter-name>SSOFilter</filter-name><url-pattern&g…

Linux I2C 驱动实验

目录 一、Linux I2C 驱动简介 1、I2C 总线驱动 2、I2C 设备驱动 1、 i2c_client 结构体 2、 i2c_driver 结构体 二、硬件分析 三、设备树编写 1、pinctrl_i2c1 2、在 i2c1 节点追加 ap3216c 子节点 3、验证 四、 代码编写 1、makefile 2、ap3216c.h 3、ap3216c.c …

开发者进阶必备的9个Tips Tricks!

优秀的开发人员市场前景是十分广阔的&#xff0c;但想找到一份理想的工作&#xff0c;仅有代码知识是不够的。优秀的工程师应该是一个终身学习者、问题的创造性解决者&#xff0c;着迷于整个软件世界。要成为一名优秀的开发者&#xff0c;应该具备哪些品质并做出哪些努力&#…

STP详解

STP STP全称为“生成树协议”&#xff08;Spanning Tree Protocol&#xff09;&#xff0c;是一种网络协议&#xff0c;用于在交换机网络中防止网络回路产生&#xff0c;保证网络的稳定和可靠性。它通过在网络中选择一条主路径&#xff08;树形结构&#xff09;&#xff0c;并…

【vulhub漏洞复现】redis 4-unacc 未授权访问漏洞

一、漏洞详情影响版本 Redis 2.x&#xff0c;3.x&#xff0c;4.x&#xff0c;5.xRedis默认情况下&#xff0c;会绑定在0.0.0.0:6379(在redis3.2之后&#xff0c;redis增加了protected-mode&#xff0c;在这个模式下&#xff0c;非绑定IP或者没有配置密码访问时都会报错)&#x…

Linux:https静态网站搭建案例

目录介绍httpshttps通信过程例介绍https 整个实验是在http实验基础上进行的 因为http协议在传输的时候采用的是明文传输&#xff0c;有安全隐患&#xff0c;所以出现了https&#xff08;安全套接字层超文本传输协议&#xff09; HTTPS并不是一个新协议&#xff0c; 而是HTTP…

【YOLO系列】YOLOv5超详细解读(网络详解)

前言 吼吼&#xff01;终于来到了YOLOv5啦&#xff01; 首先&#xff0c;一个热知识&#xff1a;YOLOv5没有发表正式论文哦~ 为什么呢&#xff1f;可能YOLOv5项目的作者Glenn Jocher还在吃帽子吧&#xff0c;hh 目录 前言 一、YOLOv5的网络结构 二、输入端 &#xff08;1…

微软发布多模态版ChatGPT!取名“宇宙一代”

文&#xff5c;CoCo酱Ludwig Wittgenstein曾说过&#xff1a;“我语言的局限&#xff0c;即是我世界的局限”。大型语言模型&#xff08;LLM&#xff09;已成功地作为各种自然语言任务的通用接口&#xff0c;只要我们能够将输入和输出转换为文本&#xff0c;就可以将基于LLM的接…

爱普生L805开机后所有灯一起闪烁不打印

故障现象: 爱普生L805彩色喷墨打印机开机后所有灯全闪烁,不能打印了?(电源灯、WiFi灯闪绿色,状态 灯、墨水灯、缺纸灯闪红色;) </

【正点原子FPGA连载】第二十二章IP封装与接口定义实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十二章IP封装…