一 内存分区

内存的分区变量存储,一般可以分为以下五个区,它们分别是:

可读可写     堆区:使用malloc、calloc、realloc、free以及c++里面的new和delete去动态申请。

可读可写 & 栈区:局部变量,函数的形参,以及大于4B的返回值。

可读可写 & 全局区:普通全局变量,静态全局变量和静态局部变量。

只读            文字常量:数值常量,字符常量,字符串常量,符号常量。

只读            代码区:代码的二进制指令。

二 变量的存储

普通局部变量

定义形式:在{}里定义的普通变量,叫做普通局部变量。

存贮区域:栈区

作用范围:每一个普通的局部变量作用范围是变量所存在的离它最近的一个完整的整个大括号范围。

生命周期:每一个普通局部变量的生命周期就是它所在的复合语句执行的周期。

一旦程序的执行(从上往下)离开了该普通局部变量的大括号范围,该普通局部变量将会被立刻回收,同时释放它所占用的内存

example:

void test01()

{

  int num1=10;//

    {

      int num2=100;

      int num1=20;

      cout<<num1<<;//输出结果为20。

      cout<<num2<<;//输出结果为100。

    }//num2的生命周期结束。

  cout<<num1<<;//输出结果为10。

  cout<<num2<<;//无效语句,会报错。

}//num1的生命周期结束。

普通全局变量

定义形式:在函数外定义的普通变量(在复合语句外定义的变量)、

存储区域:全局区

作用范围:当前源文件以及其他源文件都有效。

生命周期:整个进程

example:

int data=10;

int main()

{

  int data=20;

  cout<<data<<;//输出内容为20。

  cout<<::data<<;//通过作用域访问全局变量,输出内容为10,c语言不支持而c++支持。

}

01_code.cpp

内部有int data=100;

02_code.cpp

内部有函数void app_data() {};

欲在02_code.cpp里使用data=100,必须做一个外部声明:

extern int data;//声明data为int类型,来自于其他源文件。

void app_data()

{

  data=data+1;

}

欲在01_code.cpp里使用void app_data函数,同样需要做一个外部声明:

extern void app_data(void)

int main()

{

  app_data();

  return 0;

}

静态局部变量

定义形式:在大括号{}内加上static的变量就是静态局部变量。

存储区域:全局区

作用范围:当前所在的大括号{}复合语句都有效

生命周期:整个进程有效

example:
void test04()

{

  int data1=10;//普通局部变量

  static int data2=100;//静态局部变量

  data1++;

  data2++;

  cout<<data1<<endl;

  cout<<data2<<endl;

}

int main()

{

  test04();//data1=11,data2=101。

  test04();//data1=11,data2=102。

  test04();//data1=11,data2=103。

  test04();//data1=11,data2=104。

  //data1一直被反复定义然后释放,而data2只被定义了一次且没有被释放。

}

静态全局变量

定义形式:在函数范围外,加上static修饰定义的变量就是静态全局变量

存储区域:全局区

作用范围:只能在当前源文件使用,不能在其他源文件里使用。

生命周期:整个进程。

example:

int data1=100;//普通全局变量

static int data2=200;//静态全局变量

静态函数和全局函数

全局函数(一般函数默认为全局函数)

在当前源文件和其他源文件都可以使用,在其他源文件里使用需要加上extern外部声明。

静态函数(加上static修饰的函数)

属于静态成员,只能在当前源文件内使用。

头文件包含

<>和" "都可以用于读取头文件,但是<>是先从系统目录寻找,而" "是优先从当前目录寻找,所以最好是用<>来读取系统头文件,而" "用于读取自定义的头文件。

宏定义#define

定义形式:使用关键字define进行定义,就叫做宏。

作用范围:从当前定义开始,到整个文件结束(#undef可以结束宏的作用域)

宏定义后面不要加分号!

宏定义尽量使用大写,为了和普通变量分开

example:

#define PI 3.14

if(PI > 3)//相当于if (3.14 > 3)

{ 语句; }

//在预处理的结果,将后面有PI的地方全部用3.14来替换,而且是十分生硬的替换。

不带参数的宏:

#define PI 3.14

#define M 100

#define MY_STR "I love China"

带参数的宏(宏函数)

#define MY_MUL(a,b) a*b

cout<<MY_MUL(10,20)<<://输出的是“10*20”

宏的参数不能有类型,#define作为一个预处理,仅仅只是起到了一个替换的作用,并不能开辟空间

#define MY_MUL(int a,int b) a*b//会出错的

宏也不能保证参数的完整性,原因如上

#define MY_MUL(a,b) a*b

cout<<MY_MUL(10+20,10+30)<<;//结果为10+20*10+30,和我们的意图完全不符合

可以使用加小括号()的方式去保持参数的完整性

#define MY_MUL(a,b) (a)*(b)

宏不能作为结构体、类的成员

#define MY_MUL1(a,b) a*b

#define MY_MUL2(a,b) (a)*(b)

cout<<MY_MUL2(MY_MUL1(10+10,20+20),MY_MUL1(10+10,20+20))<<;//结果为8220

宏函数和普通函数的区别

带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈,所以带参宏是浪费了空间,因为展开多次,节省了时间;

带参函数,代码只有一份且存在代码段里,调用的时候去代码段取指令,调用的时候要压栈弹栈,有一个调用的过程。所以带参函数是节省了空间,浪费了时间。

Tips:

1.&代表可做取地址操作的意思;

2.堆区需要通过相应的接口函数才能得到地址;而文字常量区呢不允许取地址,而且字符串常量是通过特殊符号得到了它的地址;代码区我们通过函数名去得到他的地址,但是一般不能用这个去取;

3.每一个大括号{}包括其中内容在内的,这个整体被称为一条“复合语句”;

4.普通局部变量如果不初始化,那么其内容将会是不确定的(随机值);

5.普通局部变量同名遵循就近原则;

6.普通全局变量不初始化,内容默认为0;

7.全局变量和局部变量同名,优先使用局部变量;

8.extern做外部声明声明函数的时候,需要带上返回值类型,函数名和形参就够了;

9.静态局部变量若不进行初始化,内容默认为0;

10.多次反复在一个进程内定义相同一个静态局部变量,其定义只有第一次生效,后续对此的相同定义都无效(因为没有被释放过,再次定义的话就会产生冲突,所以编译器忽略了该定义的代码);

11.全局区的内容特点为未初始化的变量默认为0,且生命周期为整个进程;

12.静态全局变量若不进行初始化,内容默认为0;

13.在当前源文件内使用的好处,就是避免命名冲突(在多项目合并为一个项目的时候);

14.编译四阶段:预处理,编译,汇编,链接;

15.可执行文件,在从运行到结束,这一整个动态的过程就叫做进程;并且需要占用内存空间;

16.宏没有作用域的限制,只在当前源文件内有效。

c++学习 5 预处理的更多相关文章

  1. Linux学习---条件预处理的应用

    预处理的使用: ⑴包含头文件 #include ⑵宏定义 #define    替换,不进行语法检查 ①常量宏定义:#define 宏名 (宏体) (加括号为防止不进行语法检查而出现的错误) eg:# ...

  2. c语言学习笔记.预处理.#ifndef

    #ifndef -> if not define 配合 #endif使用 在h头文件中使用,防止重复包含和编译. 也可以用条件编译来实现. 例如: 编写头文件 test.h 在头文件开头写上两行 ...

  3. Weka学习之预处理连接MySql(二)

    载入数据 (一)打开文件 (二) 打开url (三) 打开数据库 (四)从一些数据生成器(DataGenerators)中生成人造数据    这篇主要写(三)中的连接mySql          网上 ...

  4. #pragma 预处理指令

    Linux C 编程一站式学习 #pragma 预处理指示供编译器实现一些非标准的特性,C 标准没有规定 #pragma 后面应该写什么以及起什么作用,由编译器自己规定.有的编译器用 #pragma ...

  5. 学习WEB前端是应该自学还是参加培训机构?

    先说观点,我强烈建议每个人都要自学,不要参加培训班. 我干web前端工程师这个职位已经有6年多的时间,之前在蚂蚁金服做过2年,后来离开是因为加班实在熬不住才走的,像这些已经上市的互联网公司几乎没有不加 ...

  6. 深度学习与CV教程(6) | 神经网络训练技巧 (上)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  7. Caffe︱构建lmdb数据集、binaryproto均值文件及各类难辨的文件路径名设置细解

    Lmdb生成的过程简述 1.整理并约束尺寸,文件夹.图片放在不同的文件夹之下,注意图片的size需要规约到统一的格式,不然计算均值文件的时候会报错. 2.将内容生成列表放入txt文件中.两个txt文件 ...

  8. python 小技巧

    计算时间差,时间加减运算代码 最近在学习数据预处理,碰到日期型数据不会处理,上网查了下: Q:如何方便的计算两个时间的差,如两个时间相差几天,几小时等A:使用datetime模块可以很方便的解决这个问 ...

  9. 团队作业——Alpha冲刺 3/12

    团队作业--Alpha冲刺 冲刺任务安排 杨光海天 今日任务:完成Android开发环境的搭建,学习基础开发知识 明日任务:继续学习Android开发知识,与其他成员协商,了解自己需要完成的开发任务, ...

  10. 概率dp+期望dp 题目列表(一)

    表示对概率和期望还不是很清楚定义. 目前暂时只知道概率正推,期望逆推,然后概率*某个数值=期望. 为什么期望是逆推的,例如你求到某一个点的概率我们可以求得,然后我们只要运用dp从1~n每次都加下去就好 ...

随机推荐

  1. Java pom阿里云插件

    <pluginRepositories> <pluginRepository> <id>alimaven spring plugin</id> < ...

  2. 2017GPLT

    PTA天梯赛2017GPLT 7-6 整除光棍 给定一个不以5结尾的奇数\(x\),求出数字\(n\)使得\(n*x=11...111\),输出数字n和1的位数 题解:模拟竖式除法 我们一开始发现n只 ...

  3. js 自定義event

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. From逗号是Sql92语法

    From 逗号是Sql92语法 Join on 是 Sql99语法 Sql92 外连接(+)语法,mysql不支持,oracle支持 (inner) join on   内连接 left / righ ...

  5. AWS RedShift实战应用SQL大全及经验分享[持续更新]

    文章目录 前言 - 关于RedShift 一.数据维护篇 1.1 表结构操作 1.2 数据添加与查询 1.3 数据修改与删除 1.4 事物操作 二.SQL结构篇 2.1 使用with封装代码 2.2 ...

  6. COOP/COHP(上)-PROOUT

    晶体轨道重叠布居 COOP(crystal orbital overlap population)的一个更为直观的名称是 重叠布居权重的态密度 (overlap population-weighted ...

  7. Debian 迁移到新硬盘

    老硬盘 A,新硬盘 B,先把B分好区,做好格式化. 准备虚拟机一台,Linux LiveCD光盘或者可用的Linux虚拟机系统,把硬盘A B 映射成虚拟机可以使用的硬盘文件,根据LiveCD新建相应的 ...

  8. win10格式化U盘提示没有权限执行此操作

    解决办法参考:http://www.tpbz008.cn/post/766.html 1.gpedit.msc 2.展开计算机配置,管理模板.展开系统.选中可移动存储访问 3.所有可移动存储类:拒绝所 ...

  9. IIS管理器中远程管理其它web服务器上的IIS站点

    IIS管理器中远程管理其它web服务器上的IIS站点 当生产环境服务器和部署项目过多时, 就需要单独一台机器来统一管理这些项目, 部署配置如下: 环境:项目服务器5台,运维服务器1台 应用:由运维服务 ...

  10. CUDA Arch 代码