当前位置: 首页 > news >正文

高阶C语言之六:程序环境和预处理

本文介绍程序的环境,在Linux下对编译链接理解,较为简短,着重在于编译的步骤。

C的环境

在ANSI C(标准C语言)的任何一种实现中,存在两个不同的环境。

  • 翻译环境:在这个环境中,源代码被转换为可执行命令的机器命令。
  • 执行环境:用于实际执行代码。

编译和连接 

windows环境下:源文件经编译器处理变为目标文件(.obj)再由链接器和链接库生成可执行文件(.exe)。

Linux环境下:源文件经编译器处理变为目标文件(.o)

 运行环境

程序的执行的过程:

1.        程序必须载入内存当中。再有操作系统的环境中,由操作系统完成。在独立的环境中,程序的载入必须手动安排,也可能是通过可执行代码置入只读内存来完成。

2.        程序执行的开始。调用main()函数。

3.        开始执行程序的代码。程序会使用一个运行堆栈,存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储静态内存中变量在程序的整个执行过程中一直保留它们的值。

4.        终止程序。正常终止main函数,也有可能是异常抛出。

--------------------------------------------------C环境到此结束-----------------------------------------------------------

预定义符号

__FILE__  //进行编译的源文件
__LINE__  //文件当前行号
__DATE__  //文件被编译的日期 
__TIME__  //文件被编译的时间
__STDC__  //如果编译器遵守ANSI C,其值为1,否则未定义

#define定义符号

#define指令可以定义任何语句,但是不同换行,在换行是需要特殊的换行符

#define MAX 100
#define STR "hello bit"
#define CASE break;case
#define reg register
#define do_forever for(;;)
//define语句最好不要加 ; 
//在预处理时,define会把 ; 替换到代码中
//define 定义的可以时任何语句//甚至可以时一串代码
#define DEBUG_PRINT printf("file:%s\tline=%d\t time=%s\n",\
__FILE__,\
__LINE__,\
__TIME__)\ 在define中,如果后面没有任何字符,代表续行符

#define定义宏

宏是替换的,不是通过计算的

定义宏
#define 宏名(参数列表)   宏体
/******************************/
#define SQUARE(X) ((X)*(X))
#define DOUBLE(X) ((X)+(X))//宏在定义的时候,把括号都带上
//否则会出现难以预料的错误
//这些错误没有任何语法错误,代码也可以正常运行.
//但是,最终的结果和期待的值有这很大差异
  •  参数列表的左括号必须与宏名紧邻。若果两者之间有空格,那么参数列表会被认为是宏体的一部分。
  • 带参的宏体最好把括号都带上,以防止宏的逻辑错误。
使用宏
  • 缺少括号产生的逻辑错误:
#define SQUARE(X) X*Xint main()
{int r = SQUARE(5+1);//11//等价于int r = 5 + 1 * 5 + 1;//宏是替换的,不是计算的printf("%d\n", r);return 0;}/**修正**/
#define SQUARE(X) ((X)*(X))
#define的替换规则

 在程序中扩展#define定义的符号和宏时,(三步骤):

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

#define补充 

1、#:把参数插入到字符串当
#define PRINT(N) printf("the value of "#N" is %d\n",N)
#define PRINT2(X,FORMAT) printf("the value of "#X" is "#FORMAT"\n",X)
int main()
{int a = 10;PRINT(a);//等价于printf("the value of ""a"" is %d\n",N)PRINT2(a, %d);//规定打印类型//printf("the value of a is %d\n", a);int b = 20;PRINT(b);//printf("the value of b is %d\n", b);float c = 3.02;PRINT2(c, %lf);return 0;
}
2、##:把两边的符号合并

 ##合并产生的表示符必须是合法且定义的,否则该标识符非法。

#define CAT(A,B) A##B
int main()
{int a01 = 100;printf("%d\n", CAT(a, 01));//等价于printf("%d\n", a01);return 0;
}
3、带有副作用的宏参数

        带有副作用的宏参数并不是说宏写的不好,而是参数传入带有一定的危险

        当宏的参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么在使用这个宏的时候就有可能出现危险,导致不可预测的后果。

        副作用就是表达式求值时出现的永久性的效果

#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{//int m = MAX(2, 3);int a = 5;int b = 4;int m = MAX(a++, b++);//((a++)>(b++)?(a++):(b++))//6>5?--->6++(后置++,先用,m=6) ---> a=7printf("m=%d\n", m);//6?printf("a=%d\n", a);//7printf("b=%d\n", b);//5return 0;			
}x++;//有副作用
x+1;//没有副作用
4、宏和函数

以上述宏定义的MAX(轻量运算)和函数定义Max相比,宏的优势:

  1. 宏没有参数限制,任何类型都可作比较。因此,宏是类型无关的
  2. 用于调用函数和函数返回所花费的时间更多,宏在程序的规模(更小)和速度(更快)方面更胜一筹

宏的缺点:

  1. 除非宏比较短,否则会插入大量的代码。
  2. 宏是不能调试的
  3. 宏是类型无关的,不够严谨(eg:浮点型和整型比较)。
  4. 宏会带来优先级问题,可能会导致错误。

函数是没办法以类型作为参数的。因此,宏可以做到函数做不到的事情

#define MALLOC(num,type) (type*)malloc((num)*sizeof(type))
int main()
{int* p = MALLOC(10, int);int* ptr = (int*)malloc(10*sizeof(int));return 0;
}

宏和函数对比

 4、命名约定

为了区分宏和函数:

  • 宏名一般全大写。
  • 函数名一般全小写。 

#undef移除宏定义

        #undef可以通过宏名或标识符来撤销#define的定义

#define M 100
int main()
{printf("%d\n", M);
#undef Mprintf("%d\n", M);//编译器会报错return 0;
}

命名行定义

        用Linux或者Windows系统的命令行操作指令来定义宏等。(操作系统中学习)

条件编译

        在编译一个程序的时候,我们可以通过编译指令放弃某一条语句或一端代码的编译

实例 
#define  __DEBUG__  10
int main()
{int i = 0;int arr[10] = { 0 };for (i = 0; i < 10; i++){arr[i] = i;
#ifdef __DEBUG__ //如果__DEBUG__以定义则,编译下列语句,否则不编译printf("%d\n", arr[i]);
#endif }return 0;
}

常见条件编译指令

1、单分支条件编译
int main()
{
#if 1    //#if 常量表达式printf("hehe\n");
#endif return 0;
}
2、多分支条件编译
#define M 3
int main()
{
#if M<5printf("Hehe\n");
#elif M==5printf("hah\n")
#else printf("heihei\n");
#endif 
}

在预处理时,这些未被编译代码直接被删除了。

3、 判断是否被定义
#define MAX 100
int main()
{
#ifdef MAXprintf("max\n");
#endif return 0;
}//等价于
int main()
{
#if defined(MAX)printf("max\n");
#endifreturn 0;
}//如果MAX未定义,但要编译代码
int main()
{
#ifndef MAXprintf("max\n");
#endif return 0;
}//等价于
int main()
{
#if !defined(MAX)printf("max\n");
#endifreturn 0;
}
4、嵌套指令

        #if......#endif多层嵌套实现。在库函数头文件常见。

文件包含

多重包含

头文件的多次包含会导致,代码冗余

如何防止头文件的多次重复的包含?

1、方法一:预编译指令控制

2、方法二:#pragma once

#pragma once
int Add(int x, int y)
{return x + y;
}
查找策略

-----------------------------------------------------C预处理到此结束----------------------------------------------------- #offsetof宏的实现:(在结构体对齐中计算相对于起始地址的偏移量)

#define My_offsetof(Type,member)     (size_t) &(((Type*)0)->member)struct S
{char c1;int i;char c2;
};int main()
{printf("%d\n", My_offsetof(struct S, c1));//0printf("%d\n", My_offsetof(struct S, i));//4printf("%d\n", My_offsetof(struct S, c2));//8return 0;
}

相关文章:

高阶C语言之六:程序环境和预处理

本文介绍程序的环境&#xff0c;在Linux下对编译链接理解&#xff0c;较为简短&#xff0c;着重在于编译的步骤。 C的环境 在ANSI C&#xff08;标准C语言&#xff09;的任何一种实现中&#xff0c;存在两个不同的环境。 翻译环境&#xff1a;在这个环境中&#xff0c;源代码…...

Vue 3 国际化 (i18n) 最佳实践指南

1. 安装依赖 npm install vue-i18n@9 2. 项目结构建议 src/ ├── i18n/ │ ├── index.ts # i18n 配置文件 │ ├── languages/ # 语言文件目录 │ │ ├── zh-CN.ts # 中文 │ │ ├── en-US.ts # 英文 │ │ └─…...

Acme PHP - Let‘s Encrypt

Lets Encrypt是一个于2015年三季度推出的数字证书认证机构&#xff0c;旨在以自动化流程消除手动创建和安装证书的复杂流程&#xff0c;并推广使万维网服务器的加密连接无所不在&#xff0c;为安全网站提供免费的SSL/TLS证书。 使用PHP来更新证书&#xff1a; Acme PHP | Rob…...

获取DOM 节点的四大方式

前言&#xff1a; 在 Vue 中&#xff0c;获取 DOM 节点可以通过多种方式&#xff0c;如自定义属性、ref 引用、类选择器和 ID 选择器等。 一、使用 ref 获取 DOM 实例 ref 是 Vue 中推荐的获取 DOM 节点的方式&#xff0c;它为每个节点分配一个唯一的引用&#xff0c;可以直…...

ROS2 Humble 机器人建模和Gazebo仿真

一.Ubuntu22.04系统虚拟机安装 1.下载镜像并安装 Index of /ubuntu-releases/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 2.安装选英文版&#xff0c;安装类型选清除磁盘。 3.遇到无法复制windows内容到虚拟机里。需安装VMware tools。VMware tools安装不了&a…...

docker容器镜像的制作、使用以及传递

目录 制作容器镜像使用Dockerfile制作镜像准备所需文件构建镜像怎么不使用基础镜像来构建容器镜像 使用容器镜像传递容器镜像 这篇文章讨论一下怎么使用docker制作容器镜像&#xff0c;容器镜像的使用&#xff0c;以及怎么传递容器镜像。 制作容器镜像 docker制作容器镜像推荐…...

一种由于吸入硅酸盐粉尘而引起的肺部疾病:pneumonoultramicroscopicsilicovolcanoconiosis

有人说&#xff0c;pneumonoultramicroscopicsilicovolcanoconiosis是英语中最长的单词&#xff0c;这是一个医学词汇&#xff0c;意思是指&#xff1a;一种由于吸入硅酸盐粉尘而引起的肺部疾病。 pneumonoultramicroscopicsilicovolcanoconiosis [ˈnju:mənəuˌʌltrəˌmai…...

百度AI人脸检测与对比

1.注册账号 打开网站 https://ai.baidu.com/ &#xff0c;注册百度账号并登录 2.创建应用 3.技术文档 https://ai.baidu.com/ai-doc/FACE/yk37c1u4t 4.Spring Boot简单集成测试 pom.xml 配置&#xff1a; <!--百度AI--> <dependency> <groupId>com.baidu.…...

贴代码框架PasteForm特性介绍之outer,outers,object,objects,outerdisplay

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…...

sql数据库-权限控制-DCL

目录 常用权限类别 查询用户权限 举例 授予用户权限 删除权限 常用权限类别 权限说明ALL,ALL PRIVILEGES所有权限SELECT查询数据INSERT插入数据UPDATE修改数据DELETE删除数据ALTER修改表DROP删除数据库/表/视图CREATE创建数据库/表 查询用户权限 show grants for 用户名…...

【计组笔记】目录

【计组笔记】机器数表示及运算https://blog.csdn.net/Resurgence03/article/details/142673325?sharetypeblog&shareId142673325&sharereferAPP&sharesourceresurgence03&sharefromlink 【计组笔记】指令系统https://blog.csdn.net/Resurgence03/article/det…...

深度学习中的Pixel Shuffle和Pixel Unshuffle:图像超分辨率的秘密武器

在深度学习的计算机视觉任务中&#xff0c;提升图像分辨率和压缩特征图是重要需求。Pixel Shuffle和Pixel Unshuffle是在超分辨率、图像生成等任务中常用的操作&#xff0c;能够通过转换空间维度和通道维度来优化图像特征表示。本篇文章将深入介绍这两种操作的原理&#xff0c;…...

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台 传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#x…...

golang操作mysql基础驱动github.com/go-sql-driver/mysql使用

golang中类似java操作mysql的jdbc一样&#xff0c;github.com/go-sql-driver/mysql也为go提供了基础接口&#xff0c;在开发中往往需要写更多的代码来满足自己的定制需求&#xff0c;java在驱动基础上有了扩展&#xff0c;orm框架诞生&#xff0c;mybatis、jpa等都是好用的扩展…...

正则表达式完全指南,总结全面通俗易懂

目录 元字符 连接符 限定符 定位符 修饰符&#xff08;标记&#xff09; 运算符优先级 普通字符集及其替换 零宽断言 正向先行断言 负向先行断言 正向后发断言 负向后发断言 捕获组 普通捕获组 命名捕获组 PS:非捕获组 正则表达式在线测试: 正则在线测试工具 …...

运维面试题.云计算面试题之三ELK

1.ELK是什么? ELK 其实并不是一款软件,而是一整套解决方案,是三个软件产品的首字母缩写 Elasticsearch:负责日志检索和储存 Logstash:负责日志的收集和分析、处理 Kibana:负责日志的可视化 这三款软件都是开源软件,通常是配合使用,而且又先后归于 Elastic.co 公司名下,…...

C# DataTable使用Linq查询详解

前奏- C# 对DataTable进行查询 C# 可以对 DataTable 进行查询。在 .NET 框架中&#xff0c;DataTable 类提供了几种方法来查询数据&#xff0c;包括 Select 方法和 AsEnumerable 扩展方法&#xff08;在 System.Data.DataSetExtensions 命名空间中&#xff09;。 使用 Select…...

【企业级分布式系统】ELK优化

文章目录 Elasticsearch作为日志存储时的优化优化ES索引设置优化线程池配置锁定内存&#xff0c;不让JVM使用Swap减少分片数、副本数 Elasticsearch作为日志存储时的优化 linux内核优化、JVM优化、ES配置优化、架构优化&#xff08;filebeat/fluentd代替logstash、加入kafka做…...

51单片机基础05 定时器

目录 一、为什么要定时器 二、定时器中断 1、定时器中断参数 2、定时器中断程序 3、定时器计数 一、为什么要定时器 前文提到&#xff0c;比如进行流水灯等操作&#xff0c;都是直接写了delay_ms这类操作。 但是在51单片机中&#xff0c;其一般就是靠双for进行的循环时延&…...

tdengine学习笔记实战-jdbc连接tdengine数据库

先上代码&#xff0c;里面有两种获取连接的方式&#xff0c;一个单例&#xff0c;一个连接池 package com.tdengine.utils;import com.alibaba.druid.pool.DruidDataSource;import java.sql.*; import java.util.Properties;public class TDConnectUtils {// 单例对象private …...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...