广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言程序环境和预处理详解分析
  • 871
分享到

C语言程序环境和预处理详解分析

2024-04-02 19:04:59 871人浏览 泡泡鱼
摘要

目录一、程序的翻译环境和运行环境程序的翻译环境链接阶段执行环境(运行环境)二、预处理详解预定义符号#define定义标识符#define定义宏#define 替换规则#和##两个预处

一、程序的翻译环境和运行环境

重点:任何ANSI C(标准C的程序)的一种实现,存在两个不同的环境

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

第2种是执行环境,它用于实际执行代码。

程序的翻译环境

翻译环境就是我们要做的编译和链接的这个动作。

1.每个.c文件都各自独立经过编译器的处理,最后又各自生成一个叫目标文件的东西(windows底下目标文件就叫做obj)

2.每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。

3.链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人 的程序库,将其需要的函数也链接到程序中。

 编译又分为三个步骤:

预编译(预处理):GCc test.c -E(指令)预处理后就会停止,gcc test .c -E >test.i输出重定向到test.i这个文件 。这个阶段,

1:完成了头文件的包含,比如#include这样指令的预处理,

2:#define定义的符号和宏的替换,

3:注释删除。这些都属于文本操作。

编译:gcc test .i -S生成 test.s文件,这阶段把C语言代码转换成汇编代码,1:语法分析,2:词法分析,3:语义分析,4:符号汇总。 

 汇编:对.s文件进行汇编,gcc test .s - c(指令)生成test.o文件(.o文件在windows叫test.obj),这阶段把汇编代码转换成了机器指令(二进制指令),生成符号表

链接阶段

把多个目标文件和链接库进行链接。

这个阶段,1:合并段表,2:符号表的合并和重定位。

执行环境(运行环境)

程序的执行过程:

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

2. 程序的执行便开始。接着便调用main函数。

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

4. 终止程序。正常终止main函数;也有可能是意外终止。

二、预处理详解

预定义符号

__FILE__      //进行编译的源文件

__LINE__     //文件当前的行号

__DATE__    //文件被编译的日期

__TIME__    //文件被编译的时间

__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

举例:写一个日志文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
 
int main()
{
	int i = 0;
	FILE* pf = fopen("log.txt", "a+");
	if (NULL == pf)
	{
		perror("fopen\n");
		return 1;
	}
	for (i = 0; i < 10; i++)
	{
		fprintf(pf, "%s %d %s %s %d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
	}
	return 0;
 
}

文件内容:

#define定义标识符

举例:

#define定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(Macro)或定义 宏(define macro)。

这个问题,的解决办法是在宏定义表达式两边加上一对括号就可以了。

#define DOUBLE( x)   ( ( x ) + ( x ) )

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中 的操作符或邻近操作符之间不可预料的相互作用。

#define 替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。

2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。

注意:

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

#和##两个预处理的工具

#可以把参数插入到字符串中 

##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符。 

带副作用的宏参数

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能 出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

例如:

x+1;//不带副作用

x++;//带有副作用

宏和函数对比 

宏通常被应用于执行简单的运算。 比如在两个数中找出较大的一个。

#define MAX(a, b) ((a)>(b)?(a):(b))

 那为什么不用函数来完成这个任务?

原因有二:

1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。 所以宏比函数在程序的规模和速度方面更胜一筹。

2. 更为重要的是函数的参数必须声明为特定的类型。 所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以 用于>来比较的类型。

宏是类型无关的。

宏的缺点:

当然和函数相比宏也有劣势的地方:

1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。

2. 宏是没法调试的 

3. 宏由于类型无关,也就不够严谨。

4. 宏可能会带来运算符优先级的问题,导致程容易出现错。

#undef移除宏

 这条指令用于移除一个宏定义。

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

代码如下:

命令行定义

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

代码如下:

linux底下,通过gcc test.c -D M=100,下面的代码就可以正常运行了

条件编译 

满足条件就编译,不满足条件就不参与编译。

代码如下:

 并不打印结果。 

#if 1为真,后面就编译,如果为0就不编译。 

头文件包含 

‘头文件包含的两种方式:

#include"add.h" 本地文件包含,自定义的函数的头文件用""

#include<add.h> 库文件包含,C语言库中提供的函数的头文件用<>

 查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标 准位置查找头文件。 如果找不到就提示编译错误

查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。 这样是不是可以说,对于库文件也可以使用 “” 的形式包含? 答案是肯定的,可以。 但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了。 

嵌套文件包含 

每个头文件的开头写:

#ifndef __TEST_H__

#define __TEST_H__

//头文件的内容

#endif   //__TEST_H__

或者:

#pragma once

就可以避免头文件的重复引入。 

总结

题主太累了,总结就不写了,已经过了零点了,要睡觉了。实在是感觉顶不住了,明天还得早起呢,希望大家也能不忘初心,坚持学下去,大家一起努力!!!!!! 

到此这篇关于C语言程序环境和预处理详解分析的文章就介绍到这了,更多相关C语言 预处理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言程序环境和预处理详解分析

本文链接: https://www.lsjlt.com/news/142629.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言程序环境和预处理详解分析
    目录一、程序的翻译环境和运行环境程序的翻译环境链接阶段执行环境(运行环境)二、预处理详解预定义符号#define定义标识符#define定义宏#define 替换规则#和##两个预处...
    99+
    2022-11-13
  • c语言的程序环境与预处理详解
    目录1.翻译环境2.运行环境3.预处理详解3.1#define定义的符号3.2#define定义的宏3.3#define的替换规则3.4#与##4.宏与函数对比5.#undef6.条...
    99+
    2022-11-13
  • C语言程序环境中的预处理详解
    目录一、翻译环境二、执行环境三、预处理1. 预处理符号2. #define定义标识符3. #define定义宏4. #和##5. 宏和函数的对比6. 条件编译7. 文件包含总结一、翻...
    99+
    2022-11-13
  • C语言程序环境中的预处理实例分析
    本篇内容介绍了“C语言程序环境中的预处理实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、翻译环境整个翻译环境大致就可以画成这样一张...
    99+
    2023-06-29
  • C语言中程序环境与预处理的示例分析
    这篇文章主要介绍了C语言中程序环境与预处理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。c语言代码的实现包含两种环境1.翻译环境,将源代码转化成可执行的机器指令2....
    99+
    2023-06-29
  • C语言中的程序环境与预处理实例分析
    本篇内容主要讲解“C语言中的程序环境与预处理实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言中的程序环境与预处理实例分析”吧!1.程序的翻译环境和执行环境在ANSI C的任何一种实现...
    99+
    2023-07-02
  • C语言中的程序环境与预处理详情
    目录1.程序的翻译环境和执行环境2.详解编译和链接2.1程序翻译环境下的编译和链接2.2深入编译和链接过程2.3运行环境3.预处理详解3.1预定义符号3.2#define3.2.1#...
    99+
    2022-11-13
  • C语言中程序环境和预处理的详细图文讲解
    目录1. 程序的翻译环境和执行环境 2. 详解编译+链接 2.1 翻译环境2.2 编译本身也分为几个阶段2.3 运行环境  3. 预处理详解3.1 预定...
    99+
    2023-02-16
    c语言程序环境和预处理的区别 c语言的编译预处理 c语言程序环境
  • C语言的程序环境与预处理你真的了解吗
    目录1.翻译环境2.运行环境3.预处理详解3.1#define定义的符号3.2#define定义的宏3.3#define的替换规则3.4#与##4.宏与函数对比5.#undef6.条...
    99+
    2022-11-13
  • 一起来学习C语言的程序环境与预处理
    目录1.程序的翻译环境和执行环境2.gcc C语言编译器来演示编译过程2.1编译2.2编译:2.3运行环境3详解预处理3.1预定义符号3.2#define3.2.1#define定义...
    99+
    2022-11-13
  • C语言程序的编译与预处理详解
    目录一、程序的编译1、 编译阶段2、链接二、预处理详解1、预定义符号2、#define定义的标识符3、#define定义的宏4、#unef总结一、程序的编译 我们写的源文件(*.c)...
    99+
    2022-11-12
  • C语言程序的编译与预处理实例分析
    本篇内容介绍了“C语言程序的编译与预处理实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!程序的翻译环境和执行环境在ANSIC的任何一种...
    99+
    2023-06-30
  • C语言详细分析宏定义与预处理命令的应用
    目录宏定义与预处理命令预处理命令 - 宏定义定义符号常量定义傻瓜表达式定义代码段预定义的宏函数 VS 宏定义预处理命令 - 条件式编译示例宏定义与预处理命令 预处理阶段:处理宏定义与...
    99+
    2022-11-13
  • 史上最强C语言分支和循环教程详解
    目录3.3 do...while()循环3.3.1 do语句的语法:3.3.2 执行流程3.3.3 do语句的特点3.3.4 do while循环中的break和continue3....
    99+
    2022-11-12
  • C语言程序的编译与预处理基础定义讲解
    目录程序的翻译环境和执行环境1.翻译环境2.运行环境预处理详解预定义符号#define#define定义宏#define替换规则#和##带副作用的宏参数宏和函数对比命名约定#unde...
    99+
    2022-11-13
  • C语言详细分析讲解多文件的程序设计
    目录一、多文件与编译器链接二、多文件之间的相互访问三、关于#include四、头文件使用的一些原则五、再论全局变量六、注意事项七、实验程序八、小结一、多文件与编译器链接 如下图所示,...
    99+
    2022-11-13
  • C语言编程数据结构线性表之顺序表和链表原理分析
    目录线性表的定义和特点线性结构的特点线性表顺序存储顺序表的元素类型定义顺序表的增删查改初始化顺序表扩容顺序表尾插法增加元素头插法任意位置删除任意位置添加线性表的链式存储数据域与指针域...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作