C语言进阶---程序环境和预处理

C语言进阶---程序环境和预处理

  • 前言
  • 一、程序的翻译环境、执行环境
  • 二、详解:C语言程序的编译+链接
  • 三、预定义符号介绍
  • 四、预处理指令 #define
  • 五、宏和函数的对比(思维导图)
  • 六、命令定义、预处理指令 #include #undef
    • 1.命名约定
    • 2.命令行定义
  • 七、条件编译

前言

那么好了好了,宝子们,从今天开始开始总结暑假博客,今天的主角:程序环境和预处理,来吧开始整活!⛳️

一、程序的翻译环境、执行环境

在ANSI C的任何一种实现中,存在两个不同的环境。

第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境,它用于实际执行代码。

二、详解:C语言程序的编译+链接

在这里插入图片描述

  • 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
  • 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
  • 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。

编译本身也分为几个阶段:
看代码:

#include <stdio.h>
//sum.c
int g_val = 2016;
void print(const char* str)
{printf("%s\n", str);
}
//test.c
int main()
{extern void print(char* str);extern int g_val;printf("%d\n", g_val);print("hello bit.\n");return 0;
}

在这里插入图片描述
这是预处理期间发生的:

#include <stdio.h>
int main()
{int i = 0;for(i=0; i<10; i++){printf("%d ", i);}return 0;
}
  1. 预处理 选项 gcc -E test.c -o test.i 预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。
  2. 编译 选项 gcc -S test.c 编译完成之后就停下来,结果保存在test.s中。
  3. 汇编 gcc -c test.c 汇编完成之后就停下来,结果保存在test.o中。

VIM学习资料
简明VIM练级攻略:
简明VIM练级攻略链接:https://coolshell.cn/articles/5426.html
给程序员的VIM速查卡
给程序员的VIM速查卡:https://coolshell.cn/articles/5479.html

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

三、预定义符号介绍

预定义符号:
在这里插入图片描述

四、预处理指令 #define

#define
#define 定义标识符:

#define MAX 1000
#define reg register          //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;)     //用更形象的符号来替换一种实现
#define CASE break;case        //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \date:%s\ttime:%s\n" ,\__FILE__,__LINE__ ,       \__DATE__,__TIME__ )

在define定义标识符的时候,要不要在最后加上 ; ?
nononono
比如:

#define MAX 1000;//错误,不建议这样写
#define MAX 1000

提示:(只要对于宏定义的来说,多加括号就完事了,肯定不会出错。)
所有用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用!
#define 替换规则:
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

  1. 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归。
  2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

五、宏和函数的对比(思维导图)

在这里插入图片描述

六、命令定义、预处理指令 #include #undef

1.命名约定

一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。 那我们平时的一个习惯是:

把宏名全部大写 函数名不要全部大写

#undef
这条指令用于移除一个宏定义。
#undef NAME
//如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除

2.命令行定义

许多C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程。 例如:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,这个特性有点用处。(假定某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大写,我们需要一个数组能够大写。)

#include <stdio.h> 
int main() 
{ int array [ARRAY_SIZE]; int i = 0; for(i = 0; i< ARRAY_SIZE; i ++) { array[i] = i; } for(i = 0; i< ARRAY_SIZE; i ++) { printf("%d " ,array[i]); } printf("\n" ); return 0; 
}

七、条件编译

在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的。因为我们有条件编译指令。

调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译。

注: 推荐《高质量C/C++编程指南》中附录的考试试卷(很重要)。
笔试题:

  1. 头文件中的 ifndef/define/endif是干什么用的?
  2. #include <filename.h> 和 #include "filename.h"有什么区别?
    其他预处理指令
    #error
    #pragma
    #line

    不做介绍,自己去了解。
    #pragma pack()在结构体部分介绍。
    参考《C语言深度解剖》学习

好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!
在这里插入图片描述

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

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

相关文章

解决uniapp打包过大问题的实用方法

开发者在使用uniapp开发跨平台应用时&#xff0c;可能会遇到打包过大的问题。过大的应用包不仅会增加用户下载和安装的成本&#xff0c;还会影响应用的性能和加载速度。本篇博客将介绍一些解决uniapp打包过大问题的实用方法&#xff0c;帮助开发者优化应用的大小和性能。 1、移…

[引擎开发] 杂谈ue4中的Vulkan

接触Vulkan大概也有大半年&#xff0c;概述一下自己这段时间了解到的东西。本文实际上是杂谈性质而非综述性质&#xff0c;带有严重的主观认知&#xff0c;因此并没有那么严谨。 使用Vulkan会带来什么呢&#xff1f;简单来说就是对底层更好的控制。这意味着我们能够有更多的手段…

“揭秘淘宝店铺所有商品接口:一键获取海量热销宝贝信息!“

淘宝店铺所有商品接口可以通过shop id或店铺主链接获取到整店商品&#xff0c;数据包括&#xff1a;商品ID&#xff0c;图片地址&#xff0c;店铺标题&#xff0c;优惠价&#xff0c;价格&#xff0c;销量&#xff0c;宝贝链接等整个店铺的商品。 要使用这个接口&#xff0c;需…

【maven私库nexus开机自启动】

linux设置nexus开机自启动_linux centos maven私服nexus安装搭建并设置开机启动 linux centos maven私服nexus安装搭建并设置开机启动&#xff0c;这里是用添加服务的方式开机启动nexus。 1.先要下载jdk并安装&#xff0c;配置java环境变量&#xff0c;直接去oracle下载把&am…

抄写Linux源码(Day17:你的键盘是什么时候生效的?)

回忆我们需要做的事情&#xff1a; 为了支持 shell 程序的执行&#xff0c;我们需要提供&#xff1a; 1.缺页中断(不理解为什么要这个东西&#xff0c;只是闪客说需要&#xff0c;后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的&#xff0c;所以需要这两个东…

使用弹性盒子flex对html进行布局和动态计算视口高度

使用弹性盒子flex对html进行布局的一个练习 height: calc(100vh - 4px); # vh表示视口高度的百分比&#xff0c;所以100vh表示整个视口的高度。 .mytxt { text-indent: 2em; /* 首航缩进2字符 */ line-height: 2; /* 2倍行高 */ padding: 8px; /* 内容与边框的距离 */ } …

SQLServer快速入门

SQL Server快速入门指南&#xff1a;从安装到基本查询 SQL Server是一款强大的关系型数据库管理系统&#xff0c;广泛用于企业和组织中。如果您是初学者或需要快速入门SQL Server&#xff0c;本文将为您提供一个简明的指南&#xff0c;从安装SQL Server到执行基本查询&#xff…

策略模式优雅实践

1 什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是一种常用的面向对象设计模式&#xff0c;它定义了一系列可互相替换的算法或策略&#xff0c;并将每个算法封装成独立的对象&#xff0c;使得它们可以在运行时动态地替换。具体来说&#xff0c;策略模式定义…

Flutter学习笔记

此篇文章用来记录学习Flutter 和 Dart 相关知识 零.Dart基本数据类型 Dart 是一种静态类型的编程语言&#xff0c;它提供了一系列基本数据类型&#xff0c;用于存储和操作不同种类的数据。以下是 Dart 中的一些基本数据类型以及它们的详细介绍&#xff1a; 1. 整数类型&#…

爱国者的润学日记-十月

首先需要科学的准备面试和润。如何进行科学的准备工作呢&#xff1f; 高效的按照面试考察内容进行针对性训练&#xff0c;按 Machine-learning-interview准备保证处于专注的心态&#xff0c;如今互联网娱乐发达&#xff0c;之前即使比赛时我也是一边比赛一边看视频。之后准备面…

Django跨域访问 nginx转发 开源浏览器

Django跨域访问 https://blog.csdn.net/lonelysnowman/article/details/128086205 nginx转发 https://blog.csdn.net/faye0412/article/details/75200607/ 开源浏览器 https://www.oschina.net/p/chromiumengine 浏览器油猴开发 https://blog.csdn.net/mukes/article/detail…

L1-035 情人节 c++解法

题目再现 以上是朋友圈中一奇葩贴&#xff1a;“2月14情人节了&#xff0c;我决定造福大家。第2个赞和第14个赞的&#xff0c;我介绍你俩认识…………咱三吃饭…你俩请…”。现给出此贴下点赞的朋友名单&#xff0c;请你找出那两位要请客的倒霉蛋。 输入格式&#xff1a; 输入…

3.2.OpenCV技能树--二值图像处理--图像腐蚀与膨胀

文章目录 1.文章内容来源2.图像膨胀处理2.1.图像膨胀原理简介2.2.图像膨胀核心代码2.3.图像膨胀效果展示 3.图像腐蚀处理3.1.图像腐蚀原理简介3.2.图像腐蚀核心代码3.3.图像腐蚀效果展示 4.易错点总结与反思 1.文章内容来源 1.题目来源:https://edu.csdn.net/skill/practice/o…

探秘小米增程汽车与仿生机器人的未来:AI大模型的潜在影响及苹果iPhone15Pro发热问题解决之道

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

nignx如何部署让前端不用清缓存就可以部署

在Nginx中&#xff0c;可以使用以下方法来部署前端应用程序&#xff0c;使前端用户无需清空缓存即可进行部署&#xff1a; 1、使用版本号&#xff1a;在前端应用程序的构建过程中&#xff0c;可以添加一个独特的版本号到应用程序的名称中。每次部署时&#xff0c;将版本号更新…

网络参考资料汇总(1)

将这段时间参考的各路大佬的资料加以汇总分类&#xff1a; &#xff08;1&#xff09;FFmpeg: 基于FFmpeg进行rtsp推流及拉流&#xff08;详细教程&#xff09; Linux 编译安装 FFmpeg 步骤&#xff08;带ffplay&#xff09; Jetson 环境安装(三):jetson nano配置ffmpeg和ngin…

mysql主从复制操作

对mysql进行主从复制的简单操作&#xff0c;只限于简单操作&#xff0c;下面的操作均在 centos8 中进行的&#xff0c;centos7也可以看&#xff0c;无妨 主从复制的操作主要分为无数据复制和有数据复制&#xff0c;但是主从关系分为好多种 主从复制 主从复制&#xff08;也称…

代买随想录二刷day57

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣647. 回文子串二、力扣516. 最长回文子序列 前言 一、力扣647. 回文子串 class Solution {public int countSubstrings(String s) {int n s.length()…

现货白银图表分析的依据

现货白银的行情图表分析其实与股票的差不多&#xff0c;投资者可以结合均线、k线的变化&#xff0c;来分析实时的行情走势。当走势图的均线呈多头排列&#xff0c;即短期、中期、长期均线依次从上到下排列并向右上方运行&#xff0c;且白银价格沿各均线向右上方拉升&#xff0c…

一文熟练使用python修改Excel中的数据

使用python修改Excel中的内容 1.初级修改 1.1 openpyxl库的功能&#xff1a; openpyxl模块是一个读写Excel 2010文档的Python库&#xff0c;如果要处理更早格式的Excel文档&#xff0c;需要用到额外的库&#xff0c;例如Xlwings。openpyxl是一个比较综合的工具&#xff0c;能…