程序的编译和链接

 

目录

翻译环境 

linux下的测试 ​编辑

预定义符号

执行环境

#define定义宏

#和##

#

##

宏参数的副作用

宏和函数对比

优点

缺点

#undef 

 条件编译

头文件包含


在标准c的任何实现中,存在两种环境——翻译环境和执行环境

翻译环境 

翻译环境生成目标文件(.obj)

linux下的测试 

预定义符号

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

vs不完全支持c标准,Linux下的gcc支持c标准。 

执行环境

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

#define定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏 或定义宏
#define name( parament-list ) stuff
其中的 parament - list 是一个由逗号隔开的符号表,它们可能出现在 stuff 中。
注意:参数列表的 左括号必须与name紧邻
如果两者之间有任何空白存在,参数列表就会被解释为 stuff 的一部分。
#define SQUARE(X) X*X//err
SQUARE(5+1)--->5+1*5+1
//正确写法:
#define SQUARE(X) ((X)*(X))
注意:
1. 宏参数和 #define 定义中可以出现其他 #define 定义的符号(优先替换)。但是对于宏,不能出现递归
2. 当预处理器搜索 #define 定义的符号的时候,字符串常量的内容并不被搜索
#define SQUARE(X) ((X)*(X))
#define X 2//正确

#和##

#

当我们想实现下面这串代码时:

	int a = 10;printf("the value of a is %d\n", a);int b = 20;printf("the value of b is %d\n", b);float f = 3.5f;printf("the value of f is %f\n", f);

有没有什么更简介的办法呢?

我们知道,c语言可以对字符串进行拼接,比如:

printf("hello"  "world");
//输出helloworld,省略了中间的空格。

修改后:

#define PRINT(val,format) printf("the value of "#val  "is " format "\n",val)
int a = 10;
PRINT(a, "%d");int b = 20;
PRINT(b, "%d");float f = 3.5f;
PRINT(f, "%f");

这里的#val相当于先对val完成替换再使之成为一个字符串("a")

##

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

宏参数的副作用

如果宏的参数在宏的定义中出现超过一次的话,如果参数带有副作用,将会导致不可预测的结果。

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

 输出结果为6,4,6

宏和函数对比

优点

        用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。 所以宏比函数在程序的规模和速度方面更胜一筹
        更为重要的是函数的参数必须声明为特定的类型。
所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以 用于> 来比较的类型。

 

#define MALLOC(type,num) (type)malloc(sizeof(type)*num)int* p = MALLOC(int*,4);//define实现自定义封装

缺点

1.宏不能调试。

2.宏可能会带来运算符优先级问题。

3.宏由于类型无关,可能会导致程序不严谨。

4.如果宏定义的代码量过大,可能会大幅增加程序的长度

 

#undef 

作用:移去#define定义的对象

 

命令行定义

此方法适用于linux操作系统用命令的方式在程序编译的时候对未定义的变量进行定义的一种方式。 

#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;
}

 命令行:
gcc test.c -D ARRAY_SIZE=10 

 条件编译

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

常见的条件编译语句:

#if 常量表达式//...
#endif
2.多个分支的条件编译
#if 常量表达式//...
#elif 常量表达式//...
#else//...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif
#elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2();#endif
#endif

与if..else很相似,不同的是条件编译会把不满足条件的代码在预处理阶段直接删除掉。 

头文件包含


本地文件包含:

#include "filename"

库文件包含:

#include <stdio.h>

嵌套包含:

comm.h comm.c 是公共模块。
test1.h test1.c 使用了公共模块。
test2.h test2.c 使用了公共模块。
test.h test.c 使用了 test1 模块和 test2 模块。
这样最终程序中就会出现两份 comm.h 的内容。这样就造成了文件内容的重复

解决方案:

开头写:

#prama once

或者

#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif

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

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

相关文章

蓝桥杯每日一题2032.10.24

蓝桥杯大赛历届真题 - C 语言 B 组 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 由于布局为两个字节为一行&#xff0c;那我们输入两个数就为一行&#xff0c;但是这两个数全部得用二进制进行表示使用bitset bitset:将一个数转化为二进制 bitset<8>:将一个数转化为8位…

C++设计模式_16_Adapter 适配器

Adapter 适配器也是属于“接口隔离”模式&#xff0c;也是间接思想在某一个层面的应用。 文章目录 1. 动机( Motivation)2. 模式定义3. 结构 (Structure)4. Adapter 适配器的代码实现5. 要点总结6. 其他参考 1. 动机( Motivation) 在软件系统中&#xff0c;由于应用环境的变化…

利用HTTP2,新型DDoS攻击峰值破纪录

亚马逊、Cloudflare 和谷歌周二联合发布消息称&#xff0c;一种依赖于 HTTP/2 快速重置技术的攻击行为对它们造成了破纪录的分布式拒绝服务 (DDoS) 攻击。 根据披露的信息&#xff0c;该攻击自8月下旬以来便一直存在&#xff0c;所利用的漏洞被跟踪为CVE-2023-44487&#xff0c…

Hand Avatar: Free-Pose Hand Animation and Rendering from Monocular Video

Github&#xff1a; https://seanchenxy.github.io/HandAvatarWeb 1、结构摘要 MANO-HD模型&#xff1a;作为高分辨率网络拓扑来拟合个性化手部形状将手部几何结构分解为每个骨骼的刚性部分&#xff0c;再重新组合成对的几何编码&#xff0c;得到一个跨部分的一致占用场纹理建…

计算机视觉的相机选型

#你一般什么时候会用到GPT?# 目前市面上的工业相机大多是基于CCD&#xff08;ChargeCoupled Device&#xff09;或CMOS&#xff08;Complementary Metal Oxide Semiconductor&#xff09;芯片的相机。一般CCD制造工艺更加复杂&#xff0c;也会更贵一点&#xff01; 1、CCD工…

网络协议--TCP的成块数据流

20.1 引言 在第15章我们看到TFTP使用了停止等待协议。数据发送方在发送下一个数据块之前需要等待接收对已发送数据的确认。本章我们将介绍TCP所使用的被称为滑动窗口协议的另一种形式的流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必…

众和策略:数据要素市场腾飞在即 游戏市场持续高增长

昨日&#xff0c;两市股指早盘弱势下探&#xff0c;午后沪指在银行、电力等板块的带动下发力拉升&#xff0c;深成指、创业板指均走高。到收盘&#xff0c;沪指涨0.48%报2988.3点&#xff0c;深成指涨0.4%报9566.1点&#xff0c;创业板指涨0.65%报1875.86点&#xff1b;两市合计…

使用Jenkins触发gitlab的webhook

满足条件&#xff1a; 首先手动构建可以完成构建 例如&#xff1a; 打开项目点击配置 在“Build Triggers”栏勾选&#xff0c;Build when a change is pushed to GitLab. GitLab webhook &#xff1b;如下 复制URL链接&#xff0c;我的链接是&#xff1a;http://192.168.44…

NAT技术与代理服务器

目录 一、NAT与NAPT技术 1.NAT技术 2.NAPT技术 &#xff08;1&#xff09;四元组的唯一性 &#xff08;2&#xff09;数据的传输过程 &#xff08;3&#xff09;NAPT的缺陷 二、代理服务器 1.正向代理和反向代理 2.代理服务器的应用 &#xff08;1&#xff09;游戏加…

小美的修路(最小生成树练习)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 3 4 1 2 3 1 1 2 2 0 1 3 1 0 2 3 3 0 输出 2 1 3 思路&#xff1a; 由题意&#xff0c;这里建造的城市需要修路&#xff0c;且每个城市之间可以联通&#xff0c;且 是 1 …

2023年马丁·加德纳聚会数学魔术分享之《不只是奇偶性的魔术》回顾

早点关注我&#xff0c;精彩不错过&#xff01; 我们的年度之约又来啦&#xff01; 2023马丁聚会盛况 三年疫情的阴霾终于渐渐散去&#xff0c;今天本是有机会线下见一见网友们的一年。本来都收到武元元的通知&#xff0c;在考虑参加一次线下&#xff0c;哪知消息还没焐热就因故…

Ant Design Vue UI框架的基础使用,及通用后台管理模板的小demo【简单】

一、创建 VUE 项目 npm create vuelatest二、安装使用 ant-design-vue 安装脚手架工具 $ npm install -g vue/cli # OR $ yarn global add vue/cli使用组件 # 安装 $ npm i --save ant-design-vue4.x全局完整注册 import { createApp } from vue; import Antd from ant-de…