程序环境与预处理

程序环境与预处理

一、程序环境

  1. C语言的程序环境主要分为翻译环境和执行环境。其中翻译环境是将源代码转换为可执行的机器指令。
    2.翻译环境又分为编译和链接两个部分。
    1.1编译又分为三个小部分

    *预编译(预处理):a.包含头文件b.注释删除。c.#define定义的常量的替换。d.#define定义的宏的替换。
    在gcc(linuxs环境下的C语言编译器)使用命令gcc test.c -E —-与编译后停止- 可以查看预编译后的内容(test.i)

    >  *编译(源代码——汇编代码):a.语法分析。b.词法分析。c.语义分析。d.符号汇总。
      gcc test.i -S 编译后停止     生成(test.s)
    

    *汇编(汇编指令——机器指令):a.形成符号表。
    gcc test.s -c 汇编后停止 生成(test.o)目标文件 elf格式,用命令readelf-s可以显示符号列表

    1.2链接
    *a.符号表合并。b.符号表重定位。c.合并段表。

    3.linuxs系统中的常用命令
    a.ls:列出当钱文件夹下的文件
    b.cd+文件名:可以进入目标文件夹
    c.pwd:显示工作路径

    二、预处理

    1. 预定符号
      FILE // 进行编译的源文件
      LINE //文件编译的行号
      DATE // 文件编译的日期
      TIME // 文件编译的时间
      STDC // 如果编译遵循ASCI C,其值为一,否则未定义。
      这些定义符号都是内置的。
printf("file:s% line:d%\n",__FILE__,__LINE__);

2.#define定义的标识符

//语法
#define name stuff
//如果定义的stuff过长都是,可以换行写,除最后一行外,每一行的最后加上\(续行符)
//define定义标识符时,结尾不建议加上;,避免会出现问题
//如下面的场景
#define max 1000;
#define max 1000
if(condition)
MAX = max;
else
max = 0;
//这里会出现语法错误

3.define定义宏

//宏的申明方式
#define name(parament-list) stuff
//其中parament-list是由一个都好隔开的符号表,可能在stuff中出现
//注意:参数列表的左括号必须与name紧邻,否则参数列表会被解释为stuff的一部分
//用于数值表达式的求职时的宏定义都应该加上括号,避免在预算时的运算优先级导致的不可预料的作用。
//例如
#define SQUARE(X) X*X
int a = 5;
printf("%d\n",SQUARE(a+1));
//不仔细看以为会打印36,但实际打印的是11.
实际上,在预编译是这段代码被替换为
printf("%d\n",a+1*a+1);
实际计算时由于优先级会先计算1*a
因此该宏的证正确定义方式为:
#define SQUARE(X) (X)*(X)
int a = 5;
printf("%d\n"SQUARE(a+1));
这是就会输出36了

看完上面这例子之后,我们再来看一个宏,这个定义是否有什莫问题吗?
#define DOUBLE(X) (X)+(X)
int a = 5;
printf("d%\n"10*DOUBLE(a));
这个程序输出的是100|55.

4.#和##
4.1——#

printf("d%","the value of"#VALUE"is""FORMATE""\N",VALUE);
int i = 10;
PRINTF("%d",i+3);
这个程序会输出:the value of i+3 is 13
//使用#可以把一个宏参数编程对应的字符串。
4.2——##
##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。
#define ADD_TO_SUM(num,value)\
sum##num += vilue;
ADD_TO_SUM(5,10);//作用给sum5增加10.

5,宏和函数

//代有副作用的宏参数
#define MAX(x,y) ((x>(y)) ? (x) : (y)
int a = 5;
int b = 8;
z = MAX(a++,y++);
printf("%d %d %d",a ,b,z);
这个程序输出结果为6910.
该程序预编译后的结果为:
z = ((a++) > (b++)) ? (a++) :(b++)

函数和宏相比的优点和缺点

  • 代码长度:宏代码会被插入到函数中,程序长度会大大增加。而函数值出现在一个地方,每次使用时,只需调用即可,使用的是同一份代码。
  • 执行速度:宏更快,函数存在调用和返回的开销。
  • 参数求值:每次使用宏定义是,会重新求值,具有副作用的参数会产生不可预料的结果,宏会带来运算优先级的问题,容易导致函数出错。而函数的参数只在被调用是求值一次,表达式的结果更容易预测。
  • 参数类型:宏不关心参数类型,只要参数传递合法,宏参数可以传类型。函数则对参数类型有严格限制,在函数参数中是绝对不可以传类型的。
  • 是否可以调试:宏不可以调试,函数可以调试。
  • 最后,函数可以调用实现链式访问,而宏不可以。

猜你喜欢

转载自blog.csdn.net/aixintianshideshouhu/article/details/81139516
今日推荐