做搜狗手机网站优化点积分商城平台
做搜狗手机网站优化点,积分商城平台,杭州市规划建设网站,佛山市网站建设分站企业目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段#xff1a; 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3 #define 替换规则 3.2.4 #和## 1. 程序的翻译环境和执… 目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3 #define 替换规则 3.2.4 #和## 1. 程序的翻译环境和执行环境
在ANSI C的任何一种实现中存在两个不同的环境。
第1种是翻译环境在这个环境中源代码被转换为可执行的机器指令。
第2种是执行环境它用于实际执行代码。 2. 详解编译链接
2.1 翻译环境 组成一个程序的每个源文件通过编译过程分别转换成目标代码object code。
每个目标文件由链接器linker捆绑在一起形成一个单一而完整的可执行程序。
链接器同时也会引入标准C函数库中任何被该程序所用到的函数而且它可以搜索程序员个人 的程序库将其需要的函数也链接到程序中。
2.2 编译本身也分为几个阶段
看代码
sum.c
int g_val 2016;
void print(const char *str)
{printf(%s\n, str);
}
test.c
#include stdio.h
int main()
{extern void print(char *str);extern int g_val;printf(%d\n, g_val);print(hello bit.\n);return 0;
} 如何查看编译期间的每一步发生了什么呢
test.c
#include stdio.h
int main()
{int i 0;for(i0; i10; i){printf(%d , i);}return 0;
}
1. 预处理 选项 gcc -E test.c -o test.i 预处理完成之后就停下来预处理之后产生的结果都放在test.i文件中。
2. 编译 选项 gcc -S test.c 编译完成之后就停下来结果保存在test.s中。
3. 汇编 gcc -c test.c 汇编完成之后就停下来结果保存在test.o中。
2.3 运行环境
程序执行的过程
1. 程序必须载入内存中。在有操作系统的环境中一般这个由操作系统完成。在独立的环境中程序 的载入必须由手工安排也可能是通过可执行代码置入只读内存来完成。
3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈stack存储函数的局部变量和返回 地址。程序同时也可以使用静态static内存存储于静态内存中的变量在程序的整个执行过程 一直保留他们的值。
4. 终止程序。正常终止main函数也有可能是意外终止。2. 程序的执行便开始。接着便调用main函数。
3. 预处理详解
3.1 预定义符号 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C其值为1否则未定义 这些预定义符号都是语言内置的。
举个例子 printf(file:%s line:%d\n, __FILE__, __LINE__); 3.2 #define
3.2.1 #define 定义标识符
语法 #define name stuff 举个例子
#define MAX 1000
#define reg register //为 register这个关键字创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长可以分成几行写除了最后一行外每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf(file:%s\tline:%d\t \date:%s\ttime:%s\n ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )
提问 在define定义标识符的时候要不要在最后加上 ; ?
比如
#define MAX 1000;
#define MAX 1000建议不要加上 ; ,这样容易导致问题。
比如下面的场景 if(condition)max MAX;
elsemax 0;这里会出现语法错误。
3.2.2 #define 定义宏
#define 机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义 宏define macro。
下面是宏的申明方式
#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表它们可能出现在stuff中。 注意
参数列表的左括号必须与name紧邻。
如果两者之间有任何空白存在参数列表就会被解释为stuff的一部分。
如 #define SQUARE( x ) x * x 这个宏接收一个参数 x .
如果在上述声明之后你把 SQUARE( 5 ); 置于程序中预处理器就会用下面这个表达式替换上面的表达式
5 * 5
警告
这个宏存在一个问题
观察下面的代码段
int a 5;
printf(%d\n ,SQUARE( a 1) );
乍一看你可能觉得这段代码将打印36这个值。
事实上它将打印11.
为什么
替换文本时参数x被替换成a 1,所以这条语句实际上变成了
printf (%d\n,a 1 * a 1 );
这样就比较清晰了由替换产生的表达式并没有按照预想的次序进行求值。
在宏定义上加上两个括号这个问题便轻松的解决了 #define SQUARE(x) (x) * (x) 这样预处理之后就产生了预期的效果 printf (%d\n,(a 1) * (a 1) ); 这里还有一个宏定义 #define DOUBLE(x) (x) (x) 定义中我们使用了括号想避免之前的问题但是这个宏可能会出现新的错误。 int a 5; printf(%d\n ,10 * DOUBLE(a)); 这将打印什么值呢
warning
看上去好像打印100但事实上打印的是55.
我们发现替换之后
printf (%d\n,10 * (5) (5));
乘法运算先于宏定义的加法所以出现了
55
这个问题的解决办法是在宏定义表达式两边加上一对括号就可以了。 #define DOUBLE( x) ( ( x ) ( x ) ) 提示 所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号避免在使用宏时由于 参数中 的操作符或邻近操作符之间不可预料的相互作用。
3.2.3 #define 替换规则
在程序中扩展#define定义符号和宏时需要涉及几个步骤。 1. 在调用宏时首先对参数进行检查看看是否包含任何由#define定义的符号。如果是它 们首先 被替换。 2. 替换文本随后被插入到程序中原来文本的位置。对于宏参数名被他们的值所替换。 3. 最后再次对结果文件进行扫描看看它是否包含任何由#define定义的符号。如果是就 重复上 述处理过程。
注意 1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏不能出现递归。 2. 当预处理器搜索#define定义的符号的时候字符串常量的内容并不被搜索。
3.2.4 #和## 如何把参数插入到字符串中
首先我们看看这样的代码
int i 10;
#define PRINT(FORMAT, VALUE)\printf(the value of #VALUE is FORMAT \n, VALUE);
...
PRINT(%d, i3);//产生了什么效果
这里输出的是不是 hello bit
答案是确定的
是。
我们发现字符串是有自动连接的特点的。
1. 那我们是不是可以写这样的代码 #define PRINT(FORMAT, VALUE)\ printf(the value is FORMAT\n, VALUE); ... PRINT(%d, 10); 这里只有当字符串作为宏参数的时候才可以把字符串放在字符串中。
1. 另外一个技巧是
使用 # 把一个宏参数变成对应的字符串。
比如
int i 10;
#define PRINT(FORMAT, VALUE)\printf(the value of #VALUE is FORMAT \n, VALUE);
...
PRINT(%d, i3);//产生了什么效果
代码中的 #VALUE 会预处理器处理为
VALUE .
最终的输出的结果应该是 the value of i3 is 13 ## 的作用 ##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符
#define ADD_TO_SUM(num, value) \sum##num value;
...
ADD_TO_SUM(5, 10);//作用是给sum5增加10.
注 这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/89423.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!