【无标题】 <程序环境>和<预处理>(也许会迟到,但永不缺席)
一、程序环境
1.编译环境
各位帅哥美女,我又来了,我一直想写这篇关于 程序环境和预处理 的博客,不要问我为什么没写,问就是没时间,现在给你一巴掌让你进入正题:
相信每一位敲过代码的同志在敲完代码准备运行时的画面是这样的:首先看一眼自己写完的代码,然后心里想着”这么无懈可击的代码一定可以实现我要的结果”,随后按下运行键,看着屏幕上滚动的信息,随即弹出运行窗口,满怀期待的看着它,漆黑的窗口承载着数不清的希望,有的人会因为这个窗口激动地手舞足蹈,感叹自己是个天才,而有的人会因为这个窗口抓耳挠腮、怀疑人生,关掉窗口再看一遍自己的代码,在调试无果后甚至会伤及可怜的键盘(盘盘那么可爱,你为什么要.....)。
扯远了,不知道大家有没有想过,从我们写好代码到运行,这中间到底发生了什么呢?
直接上图!
详细来说,编译又分为如下几阶段:
①预编译阶段: 预处理指令 --------------------------------------- 结果存储在(.i)文件中
②编译阶段: 语法分析、词义分析、符号汇总 ------- 结果存储在(.s)文件中
③汇编阶段: 形成符号表、汇编指令 -> 二进制指令… -> 结果存储在(.o)文件中
2.运行环境
(1).程序必须要载入内存中,而载入内存的方式可以简单分为两种:
①我们可以选择在有操作系统的环境,操作系统会将程序载入内存中。②我们选择使用独立的环 境时,必须要手动去将程序载入内存,或者可以编写可执行代码将程序放入只读内存中。
(2).程序开始执行后就开始调用main函数
(3).执行程序代码,这个时候会调用堆栈,用来存储函数的参数和返回地址,也会在静态内存区开辟空间用来存储静态的局部变量,存储在静态区的变量在整个执行过程中将一直保存它的值。
(4).程序终止:①正常运行完终止②意外终止
二、预处理
大家应该都见过这东西:#define xxx ,这个就是预定义符号
除此之外,还有一些内置的预定义符号:
①__FILE__ 当前被编译的源文件
②__LINE__ 当前被编译的源文件的行号
③__TIME__ 当前被编译的源文件的时间
④__DATE__ 当前被编译的源文件的日期
⑤__STDC__ 当前被编译的源文件是否遵循ANSI C,遵循值为1,否则未定义
1.#define定义标识符
语法:
#define name stuff ----- 将neme替换成stuff(在预编译阶段完成)
2.#define定义宏
#define允许将参数替换到文本中,这种实现方式成为定义宏或者宏。
语法:
#define name(parament-list) stuff
其中parement-list可以是一个由’ , ’(逗号)隔开的符号表,也可能只是一个符号,不管是二者中的哪一个,都可能会出现在stuff中。注意:name与右边的 ( 不能有空白格,否则会被当成stuff中的一部分
总结一下#define作用:我想大家也大概明白了,#define就是起到一个替换的作用。#define定义标识符时其实就是将name替换成stuff。#define定义宏跟函数有点类似,将参数传过去然后进行替换,不同的是,函数传参需要类型,而宏不用。
3.使用#define的注意事项
①用#define定义标识符和宏时要不要在末尾加上’ ; ’?
答:按照语法来说是可以的,但是最好不要这样做,因为在C语言中, ";"代表语句结束,而我们用#define就是想达到一种替换效果,而如果我们在#define定义时加了";",这就使我们在编写代码时简介的改变了编写时的语法习惯,所以最好不要再末尾加’ ; ’。
例:
#define MY_NAME “songsong”;
int main()
{ char* p = MY_NAME;//我们习惯的书写格式,这里在编译时就出现语法错误了 return 0;
}
②#define定义宏要加上( )
答:一定要加!
也许很多人在会将#define定义的宏与函数认为是同一种东西,这里可以很明确的告诉大家,并不是,尽管用法相同,长相相同,但是①从内存的角度说完全是两回事,#define定义的宏是在编译之前就进行处理了,也就是预处理阶段,而函数则是在编译时开辟堆栈②从性能来说也有区别,#define定义宏只是进行一个替换,而函数则是进行运算。这也是为什么#define定义宏加()的原因,因为它只起到了一个替换的作用。
例:
#define add(x) x + x // 正确: #define add(x) (x+x)
int main()
{int sum = 0;sum = 5*add(10); //原意:5*(10+10)=100//实际:5*10+10=60return 0;
}
因此,大家能看出()的重要性了吧!
③#define定义宏最好不要使参数自增
#define fun(a,b) ((a+1)*(b+1))
int main()
{int x = 3;int y = 4;int z = fun(x++,y);//注意这里,不仅没有将x+1的值代入进去计算,反而还使x值发生
//变化。return 0;
}
#define宏 总结:
①在调用宏进行替换时,首先对宏的参数进行检查,若参数含有宏替换,那么它们首先被替换。
②替换后直接插入到文本位置。
③宏不能递归
4.#和##
值得一提的是,当#define定义宏的参数部分是字符串时,那么字符串中对应的参数就不会进行替换。
①#
作用:将参数转换成对应的字符串
例:
修改前:
#define PRINT(type,value) printf(“the value is” type”\n”,value)
修改后:
#define PRINT(type,value) printf(“the”# value “is”type”\n”,value)
int main()
{int i = 0;//PRINT(“%d”,i+3);//printf(“the value is””%d””\n”,i+3),可以看到value并没有被替换PRINT(“%d”,i+3); // printf(“the””i+3””is””%d””\n”,value) // 将i+3替换成字符串return 0;
}
②##
作用:将##两侧的符号合并成为一个符号
例:
#define add(x,y) (sum##x = x+y)
int main()
{int a = 5;int b = 3;
add(3,5);//sum##3 = 3+5 ---- sum3 = 3+5reuturn 0;
}
5.宏和函数相比较
6.#undef
若需要将已经宏定义的名字进行重定义,那么首先需要移除这个名字,我们可以直接将原指令删除,然后重新#define,但是这样做太low了,我们只需要用#undef就可以将这个名字原本的定义移除。
7.条件编译指令:
①.#if:
#if 常量表达式 //常量表达式由预处理器求值 #elif 常量表达式#else 常量表达式#endif
例:
#define symbol...#if symbol#endif
…
#if必须跟随#endif收尾
②.判断是否宏定义:
#if defined(symbol)#ifdef symbol#if !defined(symbol)#ifndef symbol
8.头文件的包含
我们在使用函数时,都会引用头文件,引用的格式:#include <xxxx.h> or #include”xxxx.h”
也许大家只知道,使用库函数里的函数时采用前者的格式,使用自己编写的函数时,使用后者的格式,那么大家有没有想过为什么呢?
原因很简单,前者是去标准位置进行查找,后者是先在源文件目录下查找,若找不到,再去标准位置查找。也许有的小伙伴会说,那我使用库函数里的函数,引用头文件时,也采用#include ”xxx.h”可以吗?当然可以,只不过我们明知道我们使用的是库函数里的函数,却还这么引用,虽然最后还是会在标准位置查找文件,但这会使运行速度降低,而且让我们不容易进行区分。
好了,这部分内容就结束了,这几天好累!
【无标题】 <程序环境>和<预处理>(也许会迟到,但永不缺席)相关推荐
- C语言程序设计 | 程序环境和预处理:翻译环境和执行环境、宏、条件编译
程序环境和预处理: 翻译环境和执行环境 宏 条件编译 翻译环境和执行环境 在ANSI C的任何一种实现中,存在两种不同的环境. 第一种是翻译环境,在这个环境中源代码被转换成可执行的机器指令.第二种是执 ...
- 【C语言进阶17——程序环境和预处理】
程序环境和预处理 前言 1.程序的翻译环境和执行环境 2.详解C语言程序的编译和链接 2.1 翻译环境 2.2 编译具体阶段 2.3 查看编译每一步 2.4 程序执行的过程 3.预处理 3.1 预定义 ...
- 学C/C++想提升功底 可以花点时间看看这篇博客---C语言程序环境和预处理
本篇博客介绍了C语言程序环境和预处理.主要包含程序的翻译和运行环境和 各种预处理操作:预定义符号.各种#define 用法 undef的使用条件编译的使用 头文件包含指令 C语言程序环境和预处理 一. ...
- [C/C++]C语言的程序环境和预处理
本文主要讲述C语言的程序环境和预处理. 一.程序的翻译环境和执行环境 存在源代码转换为可执行的机器指令的翻译环境和实际执行代码的执行环境,两个不同的环境. 1.翻译环境 每个源文件通过编译 ...
- 浅谈程序环境和预处理
文章目录 前言 1. 程序的翻译环境和执行环境 2.预处理指令 1.预定义符号 2.define定义标识符 3.define定义宏 4.define替换规则 5.#的特殊作用 6.带副作用的宏参数 7 ...
- C语言提高篇——程序环境和预处理
目录 1. 程序的翻译环境和执行环境 2. 详解编译和链接 21. 编译环境 2.2 拆分编译的每个阶段 2.3 运行环境 3. 预处理详解 3.1 预处理符号 3.2 #define 3.2.1 ...
- C语言之程序环境和预处理
重点 程序的翻译环境 程序的执行环境 详解:C语言程序的编译+链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处 ...
- 程序员内功心法之程序环境和预处理
文章目录 一.程序的翻译环境和执行环境 1.翻译环境 2.执行环境 二.编译的具体过程 1.预处理 2.编译 3.汇编 三.链接的具体过程 四.编译器调用函数的规则 五.预处理操作 1.预处理符号 2 ...
- c语言程序设计1003无标题,程序员历年试题分析与解答2010年最新版-第18章 2009上半年程序员下午试题分析与解答...
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 试题一(共15分) 阅读以下说明和流程图,填补流程图中的空缺(1)-(5),将解答填入答题纸的对应栏内. [说明] 下面的流程图采用公式ex=1+x+x2 ...
- 深剖程序环境与预处理机制
目录 传统艺能
最新文章
- jQuery 7 节点遍历
- jsencrypt加密
- php 二叉树判断节点的位置,PHP实现判断二叉树是否对称的方法
- (五) shiro web应用
- Golang中WaitGroup使用的一点坑
- a.使用new关键字产生对象会调用构造方法_七夕面向对象编程,你知道Java有哪些创建对象的方式吗?...
- 计算机软考笔试知识点,计算机软考考试必备知识点:关键链法
- 黑群晖二合一已损毁_手动修复黑群晖已损毁磁盘空间
- 评:10月PMI指数新高, 带动大盘逆转, 跨年度业绩行情展开
- JAVAWEB-NOTE04
- ipad pro + zotero + 坚果云 + PDF Expert 搭建多平台文献管理(自用备忘)
- android模拟器 对比,安卓模拟器多开用哪个模拟器好?实测数据对比哪个好用
- 如何连接小米空调伴侣2
- 银联入局开启刷脸支付新战场
- 有关stm32单片机外部低速晶振LSE32.768k注意事项;RTC_WaitForSynchro()卡死;
- python小游戏----外星人入侵
- GraphScope、Neo4j与TigerGraph单机环境下性能对比
- Oracle Primavera P6系列
- 为什么功放做得这么复杂?
- 爬取百思不得姐网站上的MP4视频,有限制,必须是网页内有mp4才行,18年3月之后百思不得姐网页版改版之后不行了
热门文章
- 发明专利实质审查需要多久?
- 第十五章 奇异值分解
- Linux 下卸载nginx的操作步骤(亲测有效)
- Swift - 在fir.im上发布程序(免费的应用内测托管平台)
- git 使用简单总结
- Swift自定义导航栏返回按钮
- 计算机毕业设计Java学校图书馆管理系统(源码+系统+mysql数据库+lw文档)
- 这是关于“树先生“的故事
- 麒麟980和骁龙765g的差别盘点
- 基于Spring Security + OAuth2 的SSO单点登录(服务端)