【进阶C语言】程序环境与预处理

news2024/11/26 16:45:45

文章目录

  • 一.程序环境
    • 1.翻译环境
      • 编译器
        • 1.预处理
        • 2.编译
        • 3.汇编
      • 链接器
    • 2.运行环境
  • 总图解
  • 二.预处理
    • 1.预定义符号
    • 2.define
      • 1.define的定义
      • 2.替换规则
      • 3.定义的建议和使用的缺点
        • 1.加括号
        • 2.避免使用带有副作用的符号
        • 3.命名约定
      • 4.#和##
        • 1.#
        • 2.##
      • 5.宏和函数的对比
      • 6.undef
    • 3.条件编译
      • 1.常量表达式
      • 2.多分支
      • 3.判断是否被定义
      • 4.嵌套指令
    • 5.文件的包含——inlcude

一.程序环境

引入:我所使用的VS2019——IDE(集成开发环境)

集成开发环境:一般包括代码编辑器、编译器、调试器和图形用户界面等工具。
1.编辑器:程序编辑器是指用来进行编辑程序的软体程序。俗话就是写代码的工具
2.编译器:是一个将代码转换成二进制指令的可执行程序
3.链接器:将二进制指令进行链接生成可执行程序
4.调试器:查找代码错误的工具

思考:
1.我们写的代码能直接在计算机里面运行吗?
答案:NO,计算机只能读懂二进制指令,我们写的代码(如果正确)是能转换成二进制指令的。
如果不行需要经过怎样的步骤?(ctrl +F5)
答案:
第一步:翻译——编译,链接生成一个以后缀为.exe的可执行程序
第二步:执行——在内存中开辟空间运行生成的代码,如何开辟空间运行这里就不过多描述如果有兴趣可以看一下这篇文章——函数栈帧

1.翻译环境

说明:是将源代码转换成可执行程序的环境。
假设:我们要编译一个test.c的源文件

需要两个帮我们把代码转换成二进制指令的可执行程序(后缀.exe)
1.编译器(cl.exe)
2.链接器(link.exe)

编译器

1.预处理

生成test.i文件,并将预处理的结果放在此文件中

1.将头文件的内容包含,同时将包含的指令删除
比如:#include<stdio.h>,这里就是将stdio.h里面的内容拷贝放置在文件test.c中

2.宏指令的替换和define定义的内容的替换
比如:#define MAX 100这条指令,会被删除同时如果有int max = MAX;那么MAX会被替换成100。
注意:包含的头文件的内容也要进行此过程,这就是预处理后代码行数变少的原因

  1. 注释的删除
    注释的作用:让代码更易读懂,同时不会增加程序在运行时的负担。

2.编译

说明:将代码转换成汇编代码(通常是将高级语言转换成低级语言)
生成test.s文件,并将编译的代码放在此文件中。

如何转换呢?
涉及:
1.语义分析
2.词法分析
3.语法分析
4.符号汇总
这几步将代码的语法,符号等,拆分 转换成对应的汇编代码。

3.汇编

说明:将汇编代码转换成二进制指令
生成test.obj文件(Windows下)/test.o(Linux下),并将二进制指令放在test.o中。

这个文件的格式是elf格式的,也就是段表。
段表:每个.o文件都有相同的段表,但是每个段里面的信息可能不相同,但是同一类的信息。
1.汇编还会生成符号表。

链接器

说明:
1.将段表进行合并
2.将符号表进行汇总合并
3.生成可执行程序test.exe

符号表的合并——说白了就是将有用的信息进行筛选,无用的信息进行删除。

2.运行环境

1.程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序 的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2.程序的执行便开始。接着便调用main函数。
3.开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程
一直保留他们的值。
4.终止程序。正常终止main函数;也有可能是意外终止。

说明:
1.堆栈:是栈区
2.堆:是堆区
3.程序运行还有一种说法:函数栈帧

总图解

在这里插入图片描述

二.预处理

1.预定义符号

FILE //进行编译的源文件
LINE //文件当前的行号
DATE //文件被编译的日期
TIME //文件被编译的时间
STDC //如果编译器遵循ANSI C,其值为1,否则未定义

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	printf("%s\n", __FILE__);
	printf("%d\n", __LINE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
	//printf("%d", __STDC__);vs不遵循ANSI C
	return 0;
}

2.define

1.define的定义

#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
注意:
1.参数列表的左括号必须与name紧邻
2.如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

例如:

#define SQUARE( x ) ((x) * (x))
int main()
{
	int a = SQUARE(3);
	printf("%d", a);
	return 0;
}

图解:
在这里插入图片描述

2.替换规则

#define SQUARE( x ) ((x) * (x))
int main()
{
	int a = SQUARE(3);
	//在预处理阶段就变成 int a = ((x) * (x));
	printf("%d", a);
	return 0;
}

3.定义的建议和使用的缺点

1.加括号

#define MAX(a, b) ((a)>(b)?(a):(b))//如果不加最外面的括号结果是什么?
int main()
{
	int a = 5;
	int b = 6;
	int max = 2*MAX(5, 6);
	printf("%d",max);
	return 0;
}

加上括号确保了define定义的是一个独立且不被外部符号干扰的整体

2.避免使用带有副作用的符号

例如:++,- -等

#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
int main()
{
	int x = 5;
	int y = 8;
	int z = MAX(x++, y++);
	printf("x=%d y=%d z=%d\n", x, y, z);
	return 0;
}

在这里插入图片描述
解析:
在这里插入图片描述

3.命名约定

宏命名一般使用全大写,函数名部分或者不大写

4.#和##

1.#

功能:将宏里面的参数进行替换转换成字符串
实现一个宏:PRINT(10,i)
效果为:The value of i is 10.字符串里面的i可以换成其它字符

#define	PRINTF(value,name) printf("The value of "#name" is %d",value)
int main()
{
	int i = 10;
	PRINTF(10, i);
	return 0;
}

2.##

功能:将符号进行粘连,形成一个新的符号(必须是合法的)

#define STICK(a,b) a##b
int main()
{

	int sb = 10;
	printf("%d", STICK(s, b));
	return 0;
}

结果:10

5.宏和函数的对比

在这里插入图片描述

当代码量足够大时,使用函数比较方便,代码较为简便时使用宏比较方便

6.undef

取消define命名的符号

#define STICK(a,b) a##b

int main()
{
	int sb = 10;
	printf("%d", STICK(s, b));
    #undef STICK//取消对STICK的命名
	return 0;
}

3.条件编译

1.常量表达式

#if 常量表达式
//...
#endif
//常量表达式由预处理器求值。
//如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif

2.多分支

#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif

3.判断是否被定义

#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol

4.嵌套指令

#if defined(OS_UNIX)
	#ifdef OPTION1
	unix_version_option1();
	#endif
	#ifdef OPTION2
	unix_version_option2();
	#endif
#elif defined(OS_MSDOS)
	#ifdef OPTION2
	msdos_version_option2();
	#endif
#endif

可以将 if else语句与其和起来记忆。

5.文件的包含——inlcude

在这里插入图片描述

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

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

相关文章

趣味三角——第3章——6个三角函数的成熟过程

目录 3.1 6个三角函数的演化进程简述 3.2 Johann Muller(别名Regiomontanus)的贡献 第3章 6个三角函数的成熟过程 It is quite difficult to describe with certainty the beginning of trigonometry . . . . In general, one may say that the emphasis was placed first …

ThinkPHP5 Request类method任意方法调用RCE

ThinkPHP v5.0.x 影响版本&#xff1a;5.0.0 < version < 5.0.23 漏洞点&#xff1a;\think\Request::method 修复&#xff1a;版本更新 top-think/framework4a4b5e6 改进Request类 环境 thinkphp5.0.23核心版&#xff08;需开启debug&#xff09;thinkphp5.0.22完…

设计模式 - 六大设计原则之LoD(迪米特法则原则)

文章目录概述Case学生类老师类Bad ImplBetter Impl老师类改造调用方&#xff1a;校长类改造概述 迪米特法&#xff08;Law Of Demeter &#xff0c; LoD&#xff09;则又叫最少知道原则&#xff08;Least Knowledge Principle&#xff09;&#xff0c;最早是在1987年由美国Nor…

【游戏客户端】如何实现环形进度条

【游戏客户端】如何实现环形进度条 Hello大家好&#xff0c;我是Lampard。好久没写博客了&#xff0c;之前在忙着制作项目的一个大的副本&#xff0c;趁着过年得闲&#xff0c;和大家分享一下制作过程中遇到的一些有趣的问题。今天主要是分享如何在cocos制作一个环形的进度条 (…

重写 equals 时为什么一定要重写 hashCode

equals 方法和 hashCode 方法是 Object 类中的两个基础方法&#xff0c;它们共同协作来判断两个对象是否相等。为什么要这样设计嘞&#xff1f;原因就出在“性能” 2 字上。 使用过 HashMap 我们就知道&#xff0c;通过 hash 计算之后&#xff0c;我们就可以直接定位出某个值存…

移动web 空间转换 3D

移动web 空间转换 3D空间转换 3D3D位移透视3D旋rotateXrotateY左手法则立体呈现空间转换 3D 3D坐标系 3D 坐标系比2D 多了一个Z轴。 一定要记住3个坐标轴取值的正反&#xff1a; X 轴 往右越大&#xff0c;是正值&#xff0c; 否则反之Y 轴 往下越大&#xff0c;是正值&…

React错误边界

首先 我们先构建出问题的场景 我们创建一个react项目 然后在src下创建 components 文件夹目录 在下面创建一个 error.jsx 组件 参开代码如下 import React from "react";export default class App extends React.Component{constructor(props){super(props);this.…

CUDA编程笔记(5)

文章目录前言CUDA的内存组织全局内存常量内存纹理内存和表面内存寄存器局部内存共享内存L1和L2缓存SM的构成API函数查询设备总结前言 cuda的内存组织&#xff0c;在使用GPU时尽可能提高性能&#xff0c;合理的使用设备的内存也是十分重要的。 CUDA的内存组织 如表所示&#…

Docker基本操作

Docker基本操作一、镜像操作1.镜像名称2.镜像命令&#xff08;1&#xff09;拉取、查看镜像&#xff08;2&#xff09;保存、导入镜像二、容器操作1.容器相关命令2.创建并运行一个容器3.进入容器&#xff0c;修改文件4.小结三、数据卷&#xff08;容器数据管理&#xff09;1.什…

Java:枚举类型

Java&#xff1a;枚举类型 每博一文案 师父说&#xff1a;人活一世&#xff0c;每个人都有他的特别&#xff0c;每个人都值得被温柔相待。红尘一遭&#xff0c;每段经历都有它的必然&#xff0c; 每段经历都造就了现在的你&#xff0c;最快乐的事情&#xff0c;就是做自己&…

Java多线程案例之定时器

一. 定时器概述 1. 什么是定时器 定时器是一种实际开发中非常常用的组件, 类似于一个 “闹钟”, 达到一个设定的时间之后, 就执行某个指定好的代码. 比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连.比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自…

排序算法: 数据的离散化(排序+去重 C++例题实现)

文章目录数据的离散化例题&#xff1a;电影完整代码数据的离散化 离散化是指将一个无穷大的集合中的若干个元素映射到一个有限的集合中&#xff0c;以便于对那个无穷大的集合进行操作。 在很多情况下&#xff1a;对于一个规定在Z范围内的整数范围&#xff0c;他有可能包含非常…

maven创建自定义web工程模板

一&#xff0c;先搭建好一个项目模板。 注意每个文件夹下都放一个文件占位&#xff0c;否则创建模板时会认为是空目录不进行创建。 注意项目文件夹名字 和 pom.xml 中<artifactId 和 <name 的名字都使用相同的名字&#xff0c;写一个好记的名字&#xff0c;因为后面生…

QT UI布局设置整理-边框设置

一、设置边距的方法 1、设置容器内部的内容控件的边距 //设置容器leftBar&#xff08;QWidget&#xff09;内部marginui->leftBar->setContentsMargins(10,10,0,0); 2、 设置内部控件之间的间距 //editWidget是一个QWidget ui->editWidget->layout()->setSpac…

【云原生kubernetes】k8s中控制器使用详解

一、什么是控制器 控制器是管理pod的中间层&#xff0c;只需要告诉Pod控制器&#xff0c;想要创建多少个什么样的Pod&#xff0c;它会创建出满足条件的Pod &#xff1b;控制器相当于一个状态机&#xff0c;用来控制Pod的具体状态和行为 &#xff1b;controller会自动创建相应的…

【数据库概论】3.2 SQL的查询、更新和删除语句

一、 数据查询 SQL提供SELECT语句用于查询&#xff0c;一般格式为&#xff1a; 根据WHERE子句条件表达式从FROM子句指定的基本表、视图中找出满足条件的元组 GROUP BY语句则用作将结果按照<列名1>的值进行分组&#xff0c;该属性列值相等的元组为一个组&#xff1b;ORD…

Essential C++第五章习题

目录 5.1 5.2 5.3 5.4 5.1 C代码&#xff1a; //Stack.h#include<vector> #include<string> #include<iostream> using namespace std;#pragma once#ifndef _STACK_H_ #define _STACK_H_typedef string elemType;class Stack { public://基类的析构函数…

【JavaSE专栏5】Java 基本数据类型和取值范围

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云…

Mine Goose Duck 0.2版本发布

本次我增加了模组的1.16.5和1.18.2的适用版本&#xff0c;新增了一些职业和装扮 1.新职业 1.冒险家 你不会死于摔伤、溺水、火烧、冰冻。 2.工程师 你可以修改888范围内红石设备的状态。 3.模仿者 怪物认为你是他们的一员。 4.加拿大鹅 你会自动报警并召唤警车。 5.…

深度卷积对抗神经网络 基础 第三部分 (WGAN-GP)

深度卷积对抗神经网络 基础 第三部分 (WGAN-GP&#xff09; Wasserstein GAN with Gradient Penalty (WGAN-GP) 我们在训练对抗神经网络的时候总是出现各种各样的问题。比如说模式奔溃 (mode collapse)和 梯度消失&#xff08;vanishing gradient&#xff09;的问题。 比如说…