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

郑州网站建设推广渠道安卓aso

郑州网站建设推广渠道,安卓aso,西安哪家网站公司做的比较好,网站备案密码重置申请表1. 宏(考察很多)-要求轻松实现宏,很容易出错 #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏或定义宏。 下面是宏的声明方式: #define name(参数列表) 内容 参数列表的左括号必…

1. 宏(考察很多)-要求轻松实现宏,很容易出错

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

下面是宏的声明方式:

#define name(参数列表) 内容

参数列表的左括号必须与name紧邻,如果两者间存在空白,参数列表就会被解释成内容的一部分。

#define SQUARE(x) x*x

这个宏接收一个参数x,如果写SQUARE(5),预处理器就会用5*5这个表达式替换SQUARE(5)。

但是这个宏存在一个问题:

#define SQUARE(x) x*xint main()
{int a = 5;printf("%d\n", SQUARE(a+1));return 0;
}

我们想象中应该是6×6=36,但是实际结果居然是11,为什么呢?

SQUARE(a+1) 实际上被替换成了 a+1*a+1,并不是(a+1)*(a+1),所以结果是11。

应该在宏定义上加上两个括号:

#define SQUARE(x) (x)*(x)

如果是这样一个宏,我们吸取经验在每个x上加上括号:

#define DOUBLE(x) (x)+(x)int main()
{int a = 5;// printf("%d\n", SQUARE(a+1));printf("%d\n", 10*DOUBLE(a));return 0;
}

我们想象中是10×10=100,但是实际上是55,我们展开替换DOUBLE,实际上是10*(5)+(5)

先算10*5 = 50, 最后再+5,等于55。

所以我们要在外面也加上括号。

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

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

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

x++就是带有副作用

#define MAX(x, y) ((x)>(y)?(x):(y))int x = 5;int y = 8;int z = MAX(x++, y++);printf("%d %d %d\n", x, y, z);

预处理器处理后的结果是:

z = ((x++) > (y++) ? (x++) : (y++))

 (x++) > (y++) 都会走,走完x=6, y=9,然后走y++,z=9,y=10,最后的结果就是6,10,9。

某笔试题:

写一个宏,计算结构体中某变量相对于首地址的便宜,并给出说明

#define OFFSET_OF(type, member) ((size_t)&(((type *)0)->member))

说明:

  1. type: 结构体的类型。

  2. member: 结构体中的成员变量。

  3. ((type *)0): 将地址 0 强制转换为指向 type 类型的指针。这相当于假设结构体的首地址是 0

  4. &(((type *)0)->member): 获取成员变量 member 的地址。由于结构体的首地址是 0,这个地址就是成员变量相对于结构体首地址的偏移量。

  5. (size_t): 将偏移量转换为 size_t 类型,通常用于表示内存地址或偏移量的大小。

struct example 
{int a;char b;double c;
};int main() 
{printf("Offset of 'a': %zu\n", OFFSET_OF(struct example, a));printf("Offset of 'b': %zu\n", OFFSET_OF(struct example, b));printf("Offset of 'c': %zu\n", OFFSET_OF(struct example, c));return 0;
}
Offset of 'a': 0
Offset of 'b': 4
Offset of 'c': 8

2. 编译链接的过程(考的不多)

1. 预处理(Preprocessing)

预处理是编译过程的第一步,主要处理源代码中的预处理指令(以 # 开头的指令)。

主要任务:

  • 宏展开:将所有的宏定义展开。

  • 头文件包含:将 #include 指定的头文件内容插入到源文件中。

  • 条件编译:根据 #if#ifdef 等条件编译指令,选择性地包含或排除代码。

  • 删除注释:删除源代码中的注释。

输入输出:

  • 输入:.c 源文件。

  • 输出:.i 预处理后的文件。

gcc -E main.c -o main.i

2. 编译(Compilation)

编译阶段将预处理后的代码转换为汇编代码。

主要任务:

  • 词法分析:将源代码分解为 token(如关键字、标识符、运算符等)。

  • 语法分析:根据语法规则构建抽象语法树(AST)。

  • 语义分析:检查语义是否正确(如类型检查)。

  • 代码优化:对代码进行优化。

  • 生成汇编代码:将高级语言代码转换为目标机器的汇编代码。

输入输出:

  • 输入:.i 预处理后的文件。

  • 输出:.s 汇编文件。

gcc -S main.i -o main.s

3. 汇编(Assembly)

汇编阶段将汇编代码转换为机器代码(目标文件)。

主要任务:

  • 将汇编代码翻译为机器指令。

  • 生成目标文件(通常是 .o.obj 文件),包含机器代码和符号表。

输入输出:

  • 输入:.s 汇编文件。

  • 输出:.o 目标文件。

gcc -c main.s -o main.o

4. 链接(Linking)

链接阶段将多个目标文件和库文件合并为一个可执行文件。

主要任务:

  • 符号解析:解析目标文件中的未定义符号(如函数和变量)。

  • 地址分配:为代码和数据分配最终的内存地址。

  • 重定位:根据最终的内存地址调整代码中的引用。

  • 合并目标文件:将多个目标文件合并为一个可执行文件。

  • 链接库文件:将静态库或动态库链接到可执行文件中。

输入输出:

  • 输入:.o 目标文件和库文件。

  • 输出:可执行文件(如 a.outmain.exe)。

gcc main.o -o main
http://www.dtcms.com/wzjs/208624.html

相关文章:

  • 北京论坛网站建设网络推广外包注意哪些
  • 黑龙江建设网站万网注册域名
  • 如何用手机设计房子装修图天津seo优化公司哪家好
  • 济南网站建设求职简历天津seo诊断
  • 高仿做的最好的网站软文发稿公司
  • 百度云做网站有优势吗seo 0xu
  • ftp怎么连接网站优化大师app下载
  • 深圳做营销网站制作百度关键词刷搜索量
  • 全网营销实例seo外贸网站制作
  • 杭州公司注销流程及费用seo去哪里学
  • 青岛网站设计系统2022小说排行榜百度风云榜
  • 做外贸登录国外网站广告联盟平台排名
  • 汕头网站建设公司有哪些爱站网关键词挖掘工具站长工具
  • 进贤城乡规划建设局网站足球比赛直播2021欧冠决赛
  • 建设信用卡网站登录学校网站建设
  • 中国和住房城乡建设部网站百度app下载官方免费下载最新版
  • 济宁建设工程信息网站东莞seo优化
  • 网站开发用什么编辑器好点百度统计代码
  • wordpress 简码插件搜索引擎优化的定义是什么
  • 重庆璧山网站建设长沙网站提升排名
  • 网站模板大全下载酒店如何进行网络营销
  • 网站开发 工作量评估百度网盘app下载安装手机版
  • 网站建设详细设计合肥网络seo
  • 建网站花钱吗app引导页模板html
  • 女孩子奖励自己的资料网站排名优化专业定制
  • 嵌入式软件开发工程师是做什么的西安seo工作室
  • 国外打开国内网站慢合肥网站关键词优化公司
  • 网站建设域名注册熊掌号seo诊断方案
  • 中央经济工作会议2022何时召开优化营商环境条例解读
  • 房产信息查询北京网站优化企业