嵌入式初学-C语言-二九
C语言编译步骤
- 预处理
- 编译
- 汇编
- 链接

什么是预处理
预处理就是在源文件(如.c文件)编译之前,所进行的一部分预备操作,这部分操作是由预处理程序自动完成,当源文件在编译时,编译器会自动调用预处理指令的解析,预处理指令解析完成才能进入下一步的编译过程
为了能够方便看到编译细节,使用以下命令
gcc 源文件 -E -o 程序名[.后缀]
预处理的功能
宏定义
作用域
- fine命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。通常,#define命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。
- 可以用#undef命令终止宏定义的作用域。
- 宏定义时,可以引用已定义的宏名,可以层层置换。
- 对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。
- 宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只作字符替换,不分配内存空间。
不带参数的宏定义
- 语法:#define 宏名 常量数据的宏定义
- 预处理:此时的预处理制作数据替换,不做类型检查
- 注意:
- 定义的宏不占内存空间,还没有到编译环节的时候,就已经被替换成了宏中的常量数据
- 在预编译时将宏名替换成字符串的过程称为“宏展开”。
案例:
#include <stdio.h>
#define PI 3.1415926
void main()
{
float l,s,r,v;
printf("input radius:");
scanf("%f",&r);
l=2.0*PI*r;
s=PI*r*r;
v=4.0/3*PI*r*r*r;
printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v);
}
带参数的宏定义
- 作用:不是进行简单的字符串替换,还要进行参数替换。
- 语法:#define 宏名(参数列表)参数表达式
例题:
#define multi(a,b) a * b
/**
* 宏定义-带参数
*/
#include <stdio.h>
#define MULTI(a,b) a * b
int main()
{
int result = MULTI(7+2,3);
printf("%d\n",result);// 27 9
return 0;
}

- 对带参数的宏展开只是将语句中的宏名后面括号内的实参字符串代替#define 命令行中的形参。
- 在宏定义时,在宏名与带参数的括弧之间不应加空格,否则将空格以后的字符都作为替代字符串的一部分。
带参数的宏和函数的区别:
- 函数调用时,先求出实参表达式的值,然后代入形参。而使用带参的宏只是进行简单的字符替换。
- 函数调用是在程序运行时处理的,为形参分配临时的内存单元。而宏展开则是在编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。
- 对函数中的实参和形参类型要求一致。而宏名无类型,它的参数也无类型,只是一个符号代表,展开时代入指定的字符串即可。宏定义时,字符串可以是任何类型的数据
文件包含
概念:
所谓“文件包含”处理是指一个源文件可以将另外一个源文件的全部内容包含进来。
预处理:
此时的预处理将文件中的内容替换,文件包含指令
包含方式:
- 第一种:#include <xxxx.h>
- 系统会到标志库头文件目录(Linux下/usr/include)查找包含的文件
- 第二种:#include “xxxx.h”
- 在当前的工程路径下查找,如果未找到,任然会在标准库头文件目录查找
案例:
algorithm.h
/**
* 实现数组元素的累加计算
*/
int sum(const int *p,int len)
{
int sum = 0;
register int i = 0;
for(;i < len; i++)
{
sum += *(p+i);
}
return sum;
}
app.c
// #include <stdio.h>
// 引入自定义的头文件
#include "algorithm.h"
// 如果有n多个外部函数,难道都要一个个的使用extern进行声明?
// 引入外部函数声明
// extern int sum(const int*,int);
int main()
{
int arr[5] = {12,33,14,55,34};
int res = sum(arr,5);
printf("数组累和结果是:%d\n",res);
return 0;
}
编译命令:
gcc algorithm.c app.c -o app // 又包含关系的c文件要一起编译
说明:
(1) 一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个#include命令。
(2) 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。
(4) 在#include命令中,文件名可以用双撇号或尖括号括起来。
(5) 被包含文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。因此,如果file2.h中有全局静态变量,它也在file1.h文件中有效,不必用extern声明。
注意:
在编译时并不是分别对两个文件分别进行编译,然后再将它们的目标程序连接的,而是在经过编译预处理后将头文件format.h包含到主文件中,得到一个新的源程序,然后对这个文件进行编译,得到一个目标(.obj)文件。被包含的文件成为新的源文件的一部分,而单独生成目标文件。
条件编译
概念:
所谓“条件编译”,是对部分内容指定编译的条件,使其只在满足一定条件才进行编译。(根据设定定的条件选择待编译的语句代码)
预处理:
将满足条件的语句进行保留,不满足条件的语句进行删除,交给下一步编译
语法:
判断标识符定义或者未定义
- 语法一:
#ifdef 标识
…
#else
…
#endif
判断标识符定义或者未定义
- 语法二:
#ifndef 标识
…
#else
…
#endif
根据表达式返回的结果:0不成立,1成立
- 语法三:
#if 表达式
…
#else
…
#endif
案例:
/**
* 预处理-条件编译
*/
#define MINUS 1
int main(void)
{
#ifndef MINUS // 判断标准是:标识有没有被定义
int a = 7 - 4;
#else
int a = 7 * 4;
#endif
printf("计算结果:%d\n",a);
return 0;
}
/**
* 预处理-条件编译:输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输
出。
*/
#include <stdio.h>
// 定义一个标识
#define LETTER 0
void main()
{
// 测试用的字母字符数组
char str[20] = "C Language";
char c;
int i;
i = 0;
while((c=str[i])!='\0')
{
i++;
#if LETTER
if(c >='a' && c <='z')
{
c -= 32;
}
#else
if(c >='A' && c <='Z')
{
c += 32;
}
#endif
printf("%c",c);
}
printf("\n");
}
避免头文件重复包含的方法
语法:
#ifndef __XXXX_H
#define __XXXX_H
...
#endif
案例:
algorithm.h
/**
* 自定义头文件,专门用于存放被外部访问的函数的声明
*/
#ifndef __ALGORITHM_H
#define __ALGORITHM_H
// 数组的累加和计算
extern int sum(const int *p,int len);
#endif
相关文章:
嵌入式初学-C语言-二九
C语言编译步骤 预处理编译汇编链接 什么是预处理 预处理就是在源文件(如.c文件)编译之前,所进行的一部分预备操作,这部分操作是由预处理程序自动完成,当源文件在编译时,编译器会自动调用预处理指令的解析…...
0x03 ShowDoc 文件上传漏洞(CNVD-2020-26585)复现
参考:ShowDoc文件上传漏洞(CNVD-2020-26585)_showdoc漏洞-CSDN博客 一、fofa 搜索使用该工具的网站 网络空间测绘,网络空间安全搜索引擎,网络空间搜索引擎,安全态势感知 - FOFA网络空间测绘系统 "S…...
【大模型从入门到精通34】开源库框架LangChain 利用LangChain构建聊天机器人1
这里写目录标题 利用LangChain构建聊天机器人介绍介绍对话型聊天机器人构建环境环境变量和平台设置 加载文档和创建向量存储高级检索技术对话上下文和记忆纳入聊天历史会话缓冲内存 构建对话检索链环境设置与API密钥配置选择合适的语言模型版本Q&A系统设置 利用LangChain构…...
魔法糖果工厂
LYA 是一家魔法糖果工厂的新任管理员。工厂生产的魔法糖果有七种颜色,分别用字母 a、b、c、d、e、f、g 表示。这些糖果被排列在一条传送带上,准备进行包装。为了提高效率,工厂引进了一台智能包装机器人。这个机器人可以按照预设的指令序列来包…...
NVM安装管理node.js版本(简单易懂)
一、前言 1.1 简介 NVM(Node Version Manager)是 node.js 的版本管理器,用 shell 脚本切换机器中不同版本的 nodejs。 Nodejs为什么需要多个版本? 有经验的开发者可能遇到过,某个依赖包明确nodejs是某个版本&#…...
第1章-04-Chrome及Chrome Driver安装及测试
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师&am…...
【Linux】SSH 隧道转发场景搭建
ssh建立隧道转发 A设备:没有公网IP地址的本地设备,如本地内网服务器(需要能通公网) B设备:有公网IP地址的服务器,可以是云服务器 C设备:终端设备,想通过公网服务器B访问到设备A 要…...
前后端部署-服务器linux中安装数据库Mysql8
一、登录Xshell7 && 开放Mysql 3306端口, Redis 6379 端口 二、手动部署MySQL数据库 1.运行以下命令,更新YUM源。 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm 2.运行以下命令,安装My…...
如何使用jd-gui对springboot源码进行分析
背景: 最近在学习springboot的过滤器和拦截器,想了解一下过滤器和拦截器是怎么匹配URL的,在网上搜了半天都搜不到针对源码的,网上大部分内容都是说怎么配置过滤器和拦截器,怎么使用,并没有对源码进行分析的…...
原来ChatGPT是这么评价《黑神话:悟空》的啊?
《黑神话:悟空》一经上线便迅速吸引了全球的目光,成为了今日微博热搜榜上的焦点话题。作为中国首款现象级的中国3A大作,它的发布无疑引发了广泛的关注与讨论。 《黑神话:悟空》,这款3A国产游戏大作,由国内游…...
C语言第17篇
1.在C语言中,全局变量的存储类别是_________. A) static B) extern C) void D) register 提示:extern adj.外来的 register n.登记表,v.登记 提示与本题无关 2.在一个C源程序文件中,要定义一个只允许本源文件中所有函数使用的全局变…...
Springboot+vue实现webScoket
需求 因为在做的项目中,有多个网站登录同一个用户,故想在某一个页面登录或者退出的时候,对其他页面进行相同的操作 跨域,跨页面,跨项目,跨标签页,https 因为一开始不像麻烦后端,所以…...
CSS知识点详解:display+float
display:浮动 1.block:使元素呈现为块级元素,可设置宽高 display: block; 特点:使元素呈现为块级元素,即该元素会以新行开始,占据整行的宽度,即使其宽度未满。 例子: 2.inline&a…...
ant design pro v6 如何做好角色管理
先上图: 整个角色管理是如何做的吗? 首先你要处理后端,要先把角色存到用户那。 这是用户管理部分的内容: 可以看到一个用户是有多个角色的。 看到没有,存的是数组 数组的是一个 role 对象 role 对象是这样…...
C++ 设计模式(3. 抽象工厂模式)
抽象工厂模式也是一种创建型设计模式,提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类【引用自大话设计模式第15章】基本结构 抽象工厂模式包含多个抽象产品接口,多个具体产品类,一个抽象工厂接口和多个具体…...
【PHP入门教程】PHPStudy环境搭建+HelloWorld运行
文章目录 PHP 的历史PHP 的用途PHP 的特点和优势PHP 环境搭建环境准备安装window 安装CentOS / Ubuntu / Debian 安装 第一个Hello World使用Apache服务运行命令行运行代码 PHP 的历史 PHP(Hypertext Preprocessor)超文本预处理器是一种开源的通用脚本语…...
补 0 输出。
题目描述 输入一个整数,请在整数前面补 00 补足 88 位后输出。 输入描述 输入一行包含一个整数 nn。 输出描述 输出补00后的整数。 输入输出样例 示例1 输入 2021输出 00002021示例2 输入 202110输出 00202110 import os import sys# 请在此输入您的代码 si…...
因为嫌吵,在自己家也用上了远程控制电脑
加班嘛,赶稿嘛,参加工作的人都懂那种无形的压力和烦躁。 因为家里空间有限,我平常都是直接在客厅用台式电脑加急改写方案,但今天晚上家里来了几位叔,他们边吃饭边聊着秦始皇的话题,都70多分钟了,…...
vue---echarts环形图
1、完整代码直接可以cv <template><div id"main1"></div> </template><script> import * as echarts from echarts; // import { mapState } from vuex; // import { Alarm_Device } from ../utils/api.js; export default {name: P…...
克服编程挫折:从Bug的迷宫中寻找出口与面对算法保持冷静的策略
在编程学习的道路上,挫折感无疑是每个学习者都必须面对的挑战之一。它们仿佛是一座座高墙,阻挡我们前进的步伐。然而,正如许多有经验的编程高手所证明的那样,挫折并不是终点,而是成长和进步的催化剂。本文将分享一些有…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
rm视觉学习1-自瞄部分
首先先感谢中南大学的开源,提供了很全面的思路,减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接:https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架: 代码框架结构:readme有…...
