嵌入式C:预处理

本文详细介绍了C语言编译过程,包括预处理(头文件#include和宏定义)、编译、汇编及链接步骤,同时讲解了include、define的使用注意事项,以及选择性编译(如ifdef、ifndef和if...else)在控制代码编译中的应用。
摘要由CSDN通过智能技术生成

一、c 语言编译过程

预处理--> 编译--> 汇编--> 链接
1、 预编译
        将.c 中的头文件展开、宏展开
        生成的文件是.i 文件
2、 编译
        将预处理之后的.i 文件生成 .s 汇编文件
3 、汇编
        将.s 汇编文件生成 .o 目标文件
4 、链接
        将.o 文件链接成目标文件

二、include

#include<>// 用尖括号包含头文件,在系统指定的路径下找头文件
#include "" // 用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找。
注意:
        include 经常用来包含头文件,可以包含 .c 文件,但是不要包含 .c
        因为 include 包含的文件会在预编译被展开,如果一个 .c 被包含多次,展开多次,会导致函数重复定义。
        所以不要包含.c 文件。
注意:
        预处理只是对 include 等预处理操作进行处理并不会进行语法检查
        这个阶段有语法错误也不会报错,第二个阶段即编译阶段才进行语法检查。

三、define

定义宏用 define 去定义
宏是在预编译的时候进行替换。
1、不带参宏
#define PI 3.14
在预编译的时候如果代码中出现了 PI 就用 3.14 去替换。
宏的好处:
        只要修改宏定义,其他地方在预编译的时候就会重新替换。
注意:
        宏定义后边不要加分号
#include<stdio.h>
#define PI 3.1415
int main()
{
    double f;
    printf("%lf\n",PI);
    f=PI;
    printf("%f",f);
    return 0;
}

运行结果:

 

宏定义的作用范围,从定义的地方到本文件末尾。
如果想在中间终止宏的定义范围
#undef PI // 终止 PI 的作用
#include<stdio.h>
#define PI 3.1415926
int main()
{
    double f;
    printf("%lf\n",PI);
#undef PI
#define PI 3.14
    f=PI;
    printf("%lf\n",f);
    return 0;
}

运行结果 :

2、带参宏
#define S(a,b) a*b
注意带参宏的形参 a b 没有类型名,
S(2,4) 将来在预处理的时候替换成 实参替代字符串的形参,其他字符保留, 2 * 4
#include<stdio.h>
#define S(a,b) a*b
int main()
{
    int num;
    num=S(2,4);
    printf("num的值为:d%\n",num);
    return 0;
}

运行结果:

注意:带参宏,是在预处理的时候进行替换
解决歧义方法
#include<stdio.h>
//这里只是简单的替换,所以需要用括号括起来,到时候计算的时候不会理解错误
#define S(a,b) (a)*(b)
int main()
{
    int num;
    num=S(2+3,5);//(2+3)*(5)
    printf("num的值为:%d\n",num);
    return 0;
}

运行结果:

3 、带参宏和带参函数的区别
带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈。
所以带参宏,是浪费了空间,因为被展开多次,节省时间。
带参函数,代码只有一份,存在代码段,调用的时候去代码段取指令,调用的时候要压栈弹栈。有个调用的过程。所以说,带参函数是浪费了时间,节省了空间。
带参函数的形参是有类型的,带参宏的形参没有类型名。

 四、选择性编译

1
#ifdef  AAA
        代码段一
#else
        代码段二
#endif
如果在当前 .c 在ifdef 上定义过 AAA ,就编译代码段一,否则编译代码段二
注意和 if else 语句的区别, if else 语句都会被编译,通过条件选择性执行代码
而 选择性编译,只有一块代码被编译
#include<stdio.h>
#define AAA
int main()
{
#ifdef AAA
    printf("hello kitty!!\n");
#else
    printf("hello edu\n");
#endif
    return 0;
}

运行结果:

2、
#ifndef AAA
    代码段一
#else
    代码段二
#endif
和第一种互补。
这种方法,经常用在防止头文件重复包含。
防止头文件重复包含
#include<stdio.h>
#define AAA
int main()
{
#ifndef AAA
    printf("hello kitty!!\n");
#else
    printf("hello edu\n");
#endif
    return 0;
}

运行结果:

3
#if 表达式
    程序段一
#else
    程序段二
#endif
如果表达式为真,编译第一段代码,否则编译第二段代码
选择性编译都是在预编译阶段干的事情。

 

#include <stdio.h>

#define FLAG 1

int main() {
    #if FLAG
        printf("程序段一\n");
    #else
        printf("程序段二\n");
    #endif

    return 0;
}

运行结果:

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值