第一章 编译预处理

                课程目标git

了解嵌入式C语言编程特色和操做细节 结合嵌入式环境深刻理解指针、数组和函数 提升编程实践和编程程序规范理解 熟悉C语言标准库应用和特色github

 

                   课程结构图express

            第一章编程

第一章数组

编译预处理与位运算数据结构

编译预处理与位运算函数

 

                                            本章目标3d

本章概述指针

讲述宏定义的标准用法和位操做的基本应用调试

了解预编译的概念,掌握宏定义的方法。

了解“文件包含”与预处理的应用。 了解条件编译的几种形式。

本章目标

了解一些C语言特殊的宏定义 重点

宏定义操做

 

                 本章结构

编译预处理和位运算

编译预处理和位运算 文件包含

 

编译预处理 编译预处理

宏定义 宏定义

文件包含

条件编译 条件编译

预处理其余关键词

预处理其余关键词

                  1 编译预处理与位运算

编译预处理

宏定义

文件包含

条件编译

位运算

其余预处理关键字

 

                                                      1.1编译预处理 做用:对源程序编译以前作一些处理,生成扩展C源程序

种类

格式:

#define #ifdef #ifndef #include #if--#else--#endif等

宏定义

文件包含

条件编译

其余宏定义 #line #error #pragma

“#”开头 占单独书写行 语句尾不加分号

 

               1.2 宏定义

#undef 无参数宏定义 有参数宏定义

 

                    1.2.1 #undef #undef定义指令删除前面定义的宏名字。

表达通常形式为:

例子

#undef macro-name

#define MICRO 1 #undef MICRO

 

                             1.2.2 无参数宏定义

宏体可缺省,表示宏名 定义过或取消宏体

不带参数宏定义

通常形式: #define 宏名 [宏体] 功能:用指定标识符(宏名)代替字符序列(宏体)

如 #define YES 1

#define NO 0

#define PI 3.1415926

#define OUT printf(“Hello,World”);

例例#d#edfienfeineWWIDITDHTH8080 ()

#d#edfienfeineLELNEGNTGHTHWWIDITDHT+H4+040 v a v r =a r L = E L NE GN TG HT * H2 * ; 2 ;

if(x==YES) printf(“correct!\n”); ()

展开例后:#deifi(nxe==1P)I 3.14p1r5in9tf(“correct!\n”);

宏宏展展开开::vavr=ar8=0+8400+4*02;*2;

else if (x==NO) printf(“error!\n”);

prinetfl(s“e2*iPf (Ix==%=f0\n)”,PIp*r2in);tf(“error!\n”); 例 #define MAX MAX+10 (×)

宏展开:printf(“2*PI=%f\n”,3.14159*2); 嵌入式家园 www.embedclub.com

上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                     1.2.2 不带参数宏定义 宏定义的规则

宏名通常习惯用大写字母表示,以便与变量名相区别 宏定义不是C语句,没必要在行末加分号 在进行宏定义时,能够引用已定义的宏名,能够层层替换。 只做字符替换,不分配内存空间。

#define R 3.0

#define PI 3.1415926 结果:

#define L 2*PI*R #define S PI*R*R main()

{

L = 18.849556

}

嵌入式家园 www.embedclub.comprintf(“L=%f\nS=%f\n”,L,S);

上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

结果:

L = 18.849556

S = 28.274333

S = 28.274333

                                       1.2.2 不带参数宏定义 宏定义的特色

宏名通常习惯用大写字母表示 提升程序的通用性 宏名的有效范围为定义命令以后到本源文件结束 能够用#undef命令终止宏定义的做用域 宏定义只做简单的替换,不做正确性检查

 

             1.2.2 不带参数宏定义 练习:

定义一个宏,用于计算一年当中的秒数。定义一

 个宏,用于计算一年当中的秒数。

 

                                       1.2.3 带参数宏定义

通常形式: #define 宏名(参数表) 宏体

例 #define S(a,b) a*b ...........

不能加空格

area=S(3,2); 宏展开: area=3*2;

宏展开:形参用实参换,其它字符保留

宏体及各形参之间应加空格

注意宏体的括号

例 #define S (r) PI*r*r

例 #define POWER(x) x*x

至关于定义了不带参宏S,表明字符串“(r) PI*r*r” x=4; y=6;

z=POWER(x+y);

宏展开:z=x+y*x+y;

通常写成: #define POWER(x) ((x)*(x))

宏展开: z=((x+y)*(x+y)); 嵌入式家园 www.embedclub.com

上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                                   1.2.3 带参数宏定义 带参数宏定义的特色

带参宏定义中,宏名和形参表之间不能有空格出现

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

写为: #define MAX (a,b) (a>b)?a:b 将被认为是无参宏定义,宏名MAX表明字符串 (a,b)(a>b)?a:b

在带参宏定义中,形式参数不分配内存单元,所以没必要做类型定义

在宏定义中的形参是标识符,而宏调用中的实参能够是表达式

#define SQ(y) (y)*(y) main()

{

int a,sq;

printf("input a number: ");

scanf("%d",&a);

sq=SQ(a+1);

printf("sq=%d\n",sq);

在宏定义中,字符串内的形参一般要用括号括起来以免出错

}

 

                   1.2.3 带参数宏定义 带参的宏和带参函数很类似,但有本质上的不一样

带参宏 处理时间 编译时

函数 程序运行时

参数类型 处理过程

无类型问题

定义实参,形参类型 分配内存

不分配内存

简单的字符置换

先求实参值,再代入形参 不变

变长 运行速度 不占运行时间

程序长度

 

调用和返回占时间

                           1.2.3 带参数宏定义 带参的宏和带参函数很类似,但有本质上的不一样

函数例 宏定义例

main() {

#define SQ(y) ((y)*(y))

int i=1;

while(i<=5) printf("%d\n",SQ(i++));

main() {

}

SQ(int y) {

int i=1; while(i<=5)

return((y)*(y)); }

printf("%d\n",SQ(i++)); }

 

                                         1.3 文件包含 功能:一个源文件可将另外一个源文件的内容所有包含进来

函数例

#include “file2.c” A

file2.c

嵌入式家园 www.embedclub.com

<> 直接按标准目录搜索

“” 先在当前目录搜索,再搜索标准目录 通常形式: #include “文件名”

或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包

含”后的文件做一个源文件编译

上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

B

A file1.c file1.c

file2.c

                                            1.3 文件包含

被包含文件内容 源文件(*.c) 头文件(*.h)

file3.h

文件包含可嵌套

file1.c A

#include “file2.h”

#include “file3.h”

AB file1.c file2.h

file3.h

宏定义

数据结构定义

函数说明等

file2.h

 

C

              1.3 文件包含 例子

/* powers.h */

#define sqr(x) ((x)*(x))

#define cube(x) ((x)*(x)*(x)) #define quad(x) ((x)*(x)*(x)*(x))

#include <stdio.h>

#include "powers.h"

#define MAX_POWER 10 int main()

{ intn;

}

printf("%2d\t %3d\t %4d\t %5d\n",n,sqr(n),cube(n),quad(n)); 嵌入式家园 www.embedclub.com

printf("number\t exp2\t exp3\t exp4\n"); printf("----\t----\t-----\t------\n"); for(n=1;n<=MAX_POWER;n++)

上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                1.3 文件包含 文件包含特色

一个include命令只能指定一个被包含文件

能够用双引号括起来,也能够用尖括号括起来。

文件包含容许嵌套

被包含文件(file2.h)与其所在的文件(file.c)在预编译以后已成为同一个文 件

 

              1.4 条件编译 #if、#else、#elif #endif

#ifdef和#ifndef

                1.4.1 #if#else#elif #endif 条件编译指令中最经常使用的或许是#if,#else,#elif和#endif

#if的通常形式是:

#if constant-expression Statement sequence

#endif

#endif标记#if块的结束 例子:

#ifdef COMPUTER_A #define INTEGER_SIZE 16

#else

# define INTEGER_SIZE 32

#endif

 

                1.4.1 #if#else#elif #endif 条件编译指令中最经常使用的或许是#if,#else,#elif和#endif

#if的通常形式是:

#if constant-expression Statement sequence

#endif

#endif标记#if块的结束 例子:

#ifdef COMPUTER_A #define INTEGER_SIZE 16

#else

# define INTEGER_SIZE 32

#endif

 

                1.4.1 #if#else#elif #endif #else指令的做用与C语言的else类似,#if指令失败时它可

以做为备选指令

#else既是标记#if块的结束,也标记#else块的开始

每一个#if只能写一个#endif匹配

例子:

#include <stdio.h> #define MAX 100 int main(void)

{

}

#if MAX>99

printf(“Compiled for array greater than 99.\n”);

#else

printf(“Complied for small array.\n”);

#endif return 0;

 

              1.4.1 #if#else#elif #endif

#elif指令的意思是“不然,若是”

语法格式:

#if expression Statement sequence

#elif expression1 Statement sequence

#elif expression2 ......

#elif expression Statement sequence

#endif

 

                      1.4.2 #ifdef#ifndef #ifdef --若是已定义

#ifdef的通常形式以下: #ifdef 标识符

程序段1 #else

程序段2 #endif

当所指定的标识符已经被#define命令定义过,则在程序编译阶段只编译 程序段1,不然编译程序段2。

 

                      1.4.2 #ifdef#ifndef #ifndef --若是已定义

#ifdef的通常形式以下: #ifndef 标识符

程序段1 #else

程序段2 #endif

做用是当所指定的标识符未被#define命令定义过,则在程序编译阶段只 编译程序段1,不然编译程序段2。它只是第一行与第一种形式不一样。这 种形式与第一种形式的做用相反#ifndef

 

            1.4.2 #ifdef#ifndef #ifdef和#ifndef

#inlucde <stdio.h> #define T 10

int main(void)

{

#ifdef T

printf(“Hi T\n”);

#else

printf(“Hi anyone\n”);

#endif #ifndef M

printf(“M Not Defined\n”); #endif

return 0; }

 

                      1.4.2 #ifdef#ifndef #if --若是已定义

#if 的通常形式以下: #if 常量表达式

程序段1 #else

程序段2 #endif

如常量表达式的值为真(非0),则对程序段1 进行编译,不然对程序段2进 行编译

 

            1.4.2 #ifdef#ifndef #if 例子

#define R 1 main()

{

}

float c,r,s;

printf ("input a number: "); scanf("%f",&c);

#if R

r=3.14159*c*c;

printf("area of round is: %f\n",r); #else

s=c*c;

printf("area of square is: %f\n",s); #endif

 

            阶段小节

  宏定义的特色和宏定义的取消   带参数宏定义要注意的几个细节

  条件编译主要应用在那几个方面,它有几种使用方法  Include 包含文件的两种方法和他们之间的区别特色

 

                  1.5 其余预处理关键字

#error 使用defined #line #pragma

#和## 预约义宏

 

                               1.5.1 #error

#error指令强制编译程序中止编译

主要用于程序调试

#error指令的通常形式是 #error error-message

注意:

宏串error-message不用双引号包围 能够自定义错误内容

 

                     1.5.2 使用defined 肯定是否认义宏名字的方法

defined操做符的通常形式如 defined macro-name

肯定宏MY是否认义:define与#ifdef: #if defined MY

#ifdef MY

感叹号”!”来反转相应的条件 #if !defined DEBUG

#endif

printf(“Final Version!\n”);

 

                    1.5.3 #line

#line指令改变__LINE__和__FILE__的内容 #line的通常形式

#line number “filename” 主要用于调试和特殊应用

 

            1.5.4 ### 操做符#一般称为字符串化的操做符

#include <stdio.h> #define mkstr(s) #s int main(void)

{

}

printf(mkstr(I like C)); return 0;

预处理程序把如下的语句:

变成

printf(mkstr(I like C));

printf(“I like C”);

 

               1.5.5 ### “##”能够把两个独立的字符串链接成一个字符串

#include<stdio.h>

#define SORT(X) sort_function # # X int main(void)

}

{

结果:

结果:

char *array;

int elements,element_size;.

SORT(3) (array,elements,element_size);

SORT(3) 转化为sort_function3 SORT(3) 转化为sort_function3

SORT(3) (array,elements,element_size)转化为 SORT(3) (array,elements,element_size)转化为

sort_function3(array,elements,element_size sort_function3(array,elements,element_size

若是在运行时才能肯定要调用哪一个函数,能够利用 “##”运算符动态地构造要调用函数的名称。

 

                 1.5.6 预约义宏

__DATE__ 进行预处理的日期(“Mmm dd yyyy”形

式的字符串文字)

__FILE__ 表明当前源代码文件名的字符串文字 __LINE__ 表明当前源代码中的行号的整数常量 __TIME__ 源文件编译时间,格式微“hh:mm:ss” __func__ 当前所在函数名

 

              1.5.7 预约义宏 例子

#include <stdio.h> #include <stdlib.h> void why_me();

int main()

void why_me() {

{

printf( "The file is %s.\n", __FILE__ ); printf( "The date is %s.\n", __DATE__ ); printf( "The time is %s.\n", __TIME__ ); printf( "This is line %d.\n", __LINE__ ); printf( "This function is %s.\n",

printf( "This function is %s\n", __func__ ); printf( "The file is %s.\n", __FILE__ ); printf( "This is line %d.\n", __LINE__ );

__func__ ); why_me(); return 0;

}

 

}

            阶段小节

  位操做几个运算操做的特色   位段的特色和位段数据的引用

  位段使用的规则

  C语言扩展宏定义几个具体应用

 调试

  ##与#   #define

 

                                本章结构

编译预处理和位运算

编译预处理和位运算

文件包含 文件包含

讲述条件编译的三种应用方式

   和主要功能实现

编译预处理 编译预处理

#define定义的原则和注意事项 及应用

宏定义 宏定义

条件编译 条件编译

预处理其余关键词

预处理其余关键词

 

预处理的基础操做方式

讲述文件包含的特色和用处, 以及#include””<>的区别

讲述了#error以及#pragma和 调试输入基本应用

                本章总结

宏定义特色和注意细节 条件编译特色和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法

 

                                       实验1 题目

用宏定义来实现两个数取最大值

注意事项

?运算符的运用 对参数的包含 define的语法特色

实验结果

掌握宏定义的具体应用,深化对宏定义的操做。

 

 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

相关文章
相关标签/搜索