当前位置: 首页 > news >正文

并非从0开始的c++之旅 day2

并非从0开始的c++之旅 day2

  • 一、变量
    • 1、 变量名的本质
  • 二、程序的内存分区模型
    • 1、内存分区
      • 运行之前
      • 运行之后
  • 三、栈区注意事项
  • 四、堆区
    • 1、堆区使用
    • 2、堆区注意事项
  • 五、全局变量静态变量
    • 1、静态变量
    • 2、全局变量
  • 六、常量
    • 1、全局const常量
    • 2、局部const常量
  • 七、字符串常量

一、变量

既能读又能写的内存对象,成为变量;
若一旦初始化后不能修改的对象则称为常量。

1、 变量名的本质

变量名的本质:一段连续内存空间的别名
程序通过变量来申请和命名内存空间 int a = 0;
通过变量名访问内存空间
不是向变量名读写数据,而是向变量所代表的内存空间中读写数据;

变量修改方式:直接修改、间接修改

void test01() {int a = 10;///1、直接修改a = 20;//2、间接修改int* p = &a;//*p 解引用*p = 200;printf("a = %d\n", a);
}```自定义数据类型练习```c
struct Person {char a;int b;char c;int d;
};void test02()
{struct Person p1 = { 'a',10,'b',20 };//直接修改d属性p1.d = 100;printf("%d\n", p1.d);//间接修改d属性struct Person* p = &p1;p->d = 200;printf("%d\n", p1.d);
}

这种间接修改太简单了,我们还要学一种

若使指针p加一,p指针会跳过一个结构体的字节数
其中char类型占1个字节,int类型占4个字节,a占用0~3,b从4开始,系统用内存对齐的方式让a也占用了虽然他不使用但是在b之前的字节

结果使用以下代码验证

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

可得两值差16,同理我们可以用这种方式修改变量

	char* p = &p1;printf("%d\n", *(int*)(p + 12));printf("%d\n", *(int*)((int*)p + 3));

将p指针类型改为char *型,这时增加p指针的值会使其会一个一个往前走,在输出时,因为我们需要的是4个字节的int类型的内容,故需要做强制类型转换,将其转换为int *类型
同理如上面的第三行代码

二、程序的内存分区模型

1、内存分区

运行之前

可以简单先分为代码区和数据区
程序执行过程:

1)预处理:宏定义展开、头文件展开、条件编译,这里并不会检查语法
2)编译:检查语法,将预处理后文件编译生成汇编文件
3)汇编:将汇编文件生成目标文件(二进制文件)
4)链接:将目标文件链接为可执行程序

当我们编译完成生成可执行文件之后,我们可以通过linux下size命令可以查看一个可执行文件基本情况:
执行size命令后,系统会给出一下几个数据:

text 代码区
data 静态数据/全局初始化数据区
bss 未初始化初始化数据区
dec 文件十进制总和
hex 文件十六进制总和
filename 文件名

通过以上数据可知,在没有运行程序前,也就是说程序没有加载到内存前,可执行程序内部已经分好了3段信息,分别为代码区、数据区和未初始化数据区3个部分(有些人直接把data和bss合起来叫做静态区或全局区)

  • 代码区:存放CPU执行的机器指令。通常代码区是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了他的指令。另外,代码区还规划了局部变量的相关信息
  • 全局初始化数据区\静态数据区:该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和t)和常量数据(如字符串常量)
  • 未初始化数据区(又叫bss区):存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被内核初始化为0或空(NULL)

运行之后

相比运行之前,多出了栈区和堆区

  • 栈区(stack):栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间
  • 堆区(heap):堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

栈区:先进后出,编译器管理数据开辟,释放,容量有限,不要将大量数据开辟到栈区
堆区:容量远远大于栈区,程序员手动开辟数据,手动释放数据

三、栈区注意事项

int* fun() {int a = 10;//栈上创建的变量return &a;
}void test01() {int* p = fun();//结果依然不重要,因为上面的a早已被释放,再去操作这块数据属于非法操作printf("%d\n", *p);printf("%d\n", *p);
}

栈上的数据在执行完方法就释放了,第一次printf能打出正确结果其实是因为编译器认为你可能会处理错了数据,故保留一次,第二次打印时结果才是正常的,已经是一个随机数了。

char* GetString() {char str[] = "hello world";return str;
}void test02() {char* p = NULL;p = GetString();printf("p = %s\n", p);
}

上述代码中,将p打印后的结果为字符型乱码,因为str是指向字符串的指针,但字符串在函数运行结束后自动释放了,故他指向的地址已经为乱码,打印出来也为乱码

这里的hello world原本在常量区,无法修改,被复制了一份到栈区

两段代码告诉我们,栈上的数据出了函数体后就不要再使用了 ,也即不要返回局部变量的地址,局部变量在函数体执行完毕后会被释放,再次操作就是非法操作,结果未知!

四、堆区

1、堆区使用

int* getSpace() {int * p = malloc(sizeof(int) * 5);if (p == NULL)return NULL;for (int i = 0; i < 5; i++) {p[i] = 100 + i;}return p;
}void test01() {int* p = getSpace();for (int i = 0; i < 5; i++)printf("%d\n", p[i]);//释放数据free(p);p = NULL;
}

使用malloc创建的空间在堆区,printf多少次结果都一样,创建后如果没有使用就是垃圾,需要free
防止free后的指针仍指向原来那块已经被释放的空间,称为野指针,我们需要把它设成NULL

2、堆区注意事项

void allocateSpace(char* p) {char* temp = malloc(100);memset(temp, 0, 100);strcpy(temp, "hello world");p = temp;}void test02() {char* p = NULL;allocateSpace(p);printf("p = %s\n", p);
}

打印出来的结果为NULL,因为test中的p和函数的参数p属于同级指针,test的p为NULL时,同级指针无法改变他的值,若要改需要更高级的二级指针。
修改为以下代码

void allocateSpace2(char** p) {char* temp = malloc(100);memset(temp, 0, 100);strcpy(temp, "hello world");*p = temp;}void test03() {char* p2 = NULL;allocateSpace2(&p2);printf("p2 = %s\n", p2);
}

p一开始为NULL,参数p的值为传入p的地址,temp为堆区开辟的地址,解参数p后赋值temp,也就是将temp所含的地址赋予p,这样p就能直接指向temp所指向的堆

如果给主调函数中,一个空指针分配内存,在被调函数中利用同级指针是分配失败的
解决方式:利用高级指针修饰低级指针

五、全局变量静态变量

1、静态变量

生命周期在程序运行结束时死亡
在程序运行前就分配内存
默认属于内部链接属性,在当前文件中使用

static int a = 10;//全局作用域void test01() {static int b = 19;//局部作用域
}

默认内部链接属性,在文件外是访问不到的,如在同一个项目的另一个类中就访问不到这里的a

2、全局变量

默认在c语言下,全局变量前加了关键字 extern
属于外部链接属性

	extern int g_b;g_b = 100;

若在其他类中写了一个全局变量,想在main函数中引用,需要有第一行这个代码
这个代码就是告诉编译器,其他文件中有这么一个变量,链接时要去其他文件中寻找
但是要是找不到这个全局变量,就会报错,报错为1个无法解析的外部命令,该报错是在链接阶段报的

六、常量

1、全局const常量

//const 修饰的常量
const int a = 10;//全局const常量void test01() {//直接修改失败//a = 100;//间接修改int* p = &a;*p = 100;printf("%d\n", a);
}

如果直接修改,则a会有红线,显示语法错误
如果间接修改,vs2019会报错,显示写入访问权限冲突
全局const常量放在常量区中,受到常量区的保护

2、局部const常量

void test02() {const int b = 10;//直接修改失败//b = 100;//间接修改int* p = &a;*p = 100;printf("%d\n", b);
}

直接修改依然语法不行
间接修改正常运行,因为局部常量放在栈区,我们称之为伪常量
伪常量不可以初始化数组

七、字符串常量

void test03() {char* p1 = "hello world";char* p2 = "hello world";char* p3 = "hello world";printf("%d\n", p1);printf("%d\n", p2);printf("%d\n", p3);printf("%d\n", &"hello world");
}

由上述代码结果可知,用字符串指针指向字符串常量,得到的地址都是一样的,可知字符串常量是可以共享的

void test04() {char* p1 = "hello world";p1[0] = "w";printf("%d\n", p1);
}

运行后会报错,字符串常量是不能修改的,虽然ANSIC中规定是不定义的,但vs是不能修改的
vs会把多个相同的字符串常量看成一个

相关文章:

并非从0开始的c++之旅 day2

并非从0开始的c之旅 day2一、变量1、 变量名的本质二、程序的内存分区模型1、内存分区运行之前运行之后三、栈区注意事项四、堆区1、堆区使用2、堆区注意事项五、全局变量静态变量1、静态变量2、全局变量六、常量1、全局const常量2、局部const常量七、字符串常量一、变量 既能…...

Linux进阶(Shell编程学习一)

由于shell脚本在java项目运维方面极其重要&#xff0c;比如服务的启动脚本&#xff0c;日志的分割脚本&#xff0c;文件的管理脚本大多都是shell脚本去实现的。所以作为java开发者懂linux的基本命令&#xff0c;会基本的shell编程是必要的。 Shell 是一个用 C 语言编写的程序&…...

sql 优化

sql 优化1. mysql 基础架构1.1 mysql 的组成2. mysql 存储引擎2.1MyISAM2.2 InnoDB2.3 MyISAM 和 InnoDB 的对比3. mysql 索引3.1 Hash 索引3.2 B-Tree 索引3.3 BTree 索引3.4 R-Tree 索引3.5 Full-Text 索引4. sql 优化4.1 避免 select *4.2 避免在where子句中使用or来连接条件…...

第7篇:Java的学习路径

目录 1、Java学习主要内容概览 1.1 Java基础 1.2 数据库技术 1.3 动态网页技术 1.4中间件技术...

对抗生成网络GAN系列——Spectral Normalization原理详解及源码解析

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;专栏推荐&#xff1a;深度学习网络原理与实战 &#x1f34a;近期目标&#xff1a;写好专栏的每一篇文章 &#x1f34a;支持小苏&#xff1a;点赞&#x1f44d;&#x1f3fc;、…...

Solon2 开发之插件,一、插件

Solon Plugin 是框架的核心接口&#xff0c;简称“插件”。其本质是一个“生命周期”接口。它可让一个组件类参与程序的生命周期过程&#xff08;这块看下&#xff1a;《应用启动过程与完整生命周期》&#xff09;&#xff1a; FunctionalInterface public interface Plugin {…...

使用nvm管理node

nvm介紹 node的版本管理器&#xff0c;可以方便地安装&切换不同版本的node 我们在工作中&#xff0c;可以会有老版本的node的项目需要维护&#xff0c;也可能有新版本的node的项目需要开发&#xff0c;如果只有一个node版本的话将会很麻烦&#xff0c;nvm可以解决我们的难点…...

Linux

第一章 Linux 1.1 计算机硬件软件体系 冯诺依曼 (数学家,计算机之父) 冯诺依曼体系 计算机的指令和数据都是二进制存储,并且存放到一起程序和指令都是顺序执行的计算机硬件由输入,输出,存储,运算器与控制器组成 输入设备 比如:键盘,鼠标等. 输出设备 打印机输出&#xff0…...

GB28181-2022注册注销基本要求、注册重定向解读和技术实现

规范解读GB28181-2022注册、注销基本要求相对GB28181-2016版本&#xff0c;做了一定的调整&#xff0c;新调整的部分如下&#xff1a;——更改了注册和注销基本要求&#xff08;见 9.1.1&#xff0c;2016 年版的 9.1.1&#xff09;。1.增加对NAT模式网络传输要求&#xff0c;宜…...

2023年二建报考条件是什么?考试考什么?来考网

2023年二建报考条件是什么&#xff1f;考试考什么&#xff1f;来考网 2023年二建报考条件是什么&#xff1f;考试考什么&#xff1f;来考网 二建报考条件&#xff1a; 1、中专及以上学历 2、工程或工程经济类专业 3、从事施工管理工作满2年 二建考试科目&#xff1a; 《建设工…...

vite+vue3搭建的工程热更新失效问题

前段时间开发新的项目&#xff0c;由于没有技术上的限制&#xff0c;所以选择了vitevue3ts来开发新的项目&#xff0c;一开始用vite来开发新项目过程挺顺利&#xff0c;确实比vue2webpack的项目高效些&#xff08;为什么选择vite&#xff09;,但是过了一段时间后&#xff0c;不…...

Hazel游戏引擎(001-003)

文章目录前言001.游戏引擎介绍002.什么是游戏引擎003设计我们的游戏引擎本人菜鸟&#xff0c;文中若有代码、术语等错误&#xff0c;欢迎指正 前言 我写的项目地址 https://github.com/liujianjie/GameEngineLightWeight&#xff08;中文的注释适合中国人的你&#xff09; 关于…...

耗时一个星期整理的APP自动化测试工具大全

在本篇文章中&#xff0c;将给大家推荐14款日常工作中经常用到的测试开发工具神器&#xff0c;涵盖了自动化测试、APP性能测试、稳定性测试、抓包工具等。 一、UI自动化测试工具 1. uiautomator2 openatx开源的ui自动化工具&#xff0c;支持Android和iOS。主要面向的编程语言…...

算法设计与分析(屈婉玲)视频笔记day2

序列求和的方法 数列求和公式 等差、等比数列与调和级数 求和的例子 二分检索算法 二分检索运行实例 2 n 1个输入 比较 t 次的输入个数 二分检索平均时间复杂度 估计和式上界的放大法 放大法的例子 估计和式渐近的界 估计和式渐近的界 小结 • 序列求和基本公式&#xff1a;…...

14-PHP使用过的函数 131-140

131、session_unset 释放当前会话注册的所有会话变量。 没有返回值。 132、session_destroy 销毁当前会话中的全部数据&#xff0c; 但是不会重置当前会话所关联的全局变量&#xff0c; 也不会重置会话 cookie。 如果需要再次使用会话变量&#xff0c; 必须重新调用 session_…...

【第39天】实现一个冒泡排序

本文已收录于专栏 🌸《Java入门一百例》🌸 学习指引 序、专栏前言一、冒泡排序一、【例题1】1、题目描述2、解题思路3、模板代码三、推荐专栏序、专栏前言 本专栏开启,目的在于帮助大家更好的掌握学习Java,特别是一些Java学习者难以在网上找到系统地算法学习资料帮助自身…...

「2」线性代数(期末复习)

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 方阵的行列式 (1) &#xff5c;A^T&#xff5c;&#xff5c;A&#xff5c;(2) |&#x1d6…...

动态规划专题——背包问题

&#x1f9d1;‍&#x1f4bb; 文章作者&#xff1a;Iareges &#x1f517; 博客主页&#xff1a;https://blog.csdn.net/raelum ⚠️ 转载请注明出处 目录前言一、01背包1.1 使用滚动数组优化二、完全背包2.1 使用滚动数组优化三、多重背包3.1 使用二进制优化四、分组背包总结…...

数据的分组聚合

1&#xff1a;分组 t.groupby #coding:utf-8 import pandas as pd import numpy as np file_path./starbucks_store_worldwide.csv dfpd.read_csv(file_path) #print(df.head(1)) #print(df.info()) groupeddf.groupby(byCountry) print(grouped) #DataFrameGroupBy #可以遍历…...

【Airplay_BCT】Bonjour conformance tests苹果IOT

从Airplay开始&#xff0c;接触到BCT&#xff0c;这是什么&#xff1f;被迫从安卓变成ios用户和开发。。。开始我的学习之旅&#xff0c;记录成长过程&#xff0c;不定时更新 Bonjour 下面是苹果官网关于bonjour的解释 Bonjour, also known as zero-configuration networking, …...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...