c语言与预处理指令

本文介绍了C语言的预处理指令,包括系统文件与自定义文件的引用、宏定义的使用及其注意事项,如带参数的宏定义应如何避免错误。还讨论了条件编译和#include指令,解释了条件编译的条件以及头文件的嵌套包含可能导致的问题,提出了防止头文件重复包含的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预处理指令:在程序编译前执行,效率高,以符号#开头,没有';'结尾的编译指令,这些指令称为预处理命令,预处理命令属于C语言编译器,而不是C语言的组成部分,通过预处理命令可扩展C语言程序设计的环境,

例:

#include <stdio.h>

#include “stu.h”

#include <string.h>

系统文件用<>,自己写的用””

 

宏定义

文件包含

条件编译

定义常量

 

 

 

宏定义不仅在编译前执行,效率比较高,并且不会检测内存,如果替换之后会发生检测

#include <stdio.h>

#include "stu.h"

#include <string.h>

#define LENGTH 20 //length叫宏名,20为被宏名替换的字符串

int main(int argc, const char * argv[])

{

for (int i=0; i<LENGTH; i++) {

        printf("%i\n",i);

    }

    return 0;

}

 

在编译之前会检查所有的LENGTH并把它替换为20

带参数的宏定义注意点,宏定义的参数只做替换操作并不会做计算操作

#include <stdio.h>

#include "stu.h"

#include <string.h>

#define calcSum(a,b) a*b

int main(int argc, const char * argv[])

{

int i=calcSum(2+2,3+6);  

替换过程

// calcSum(a,b) a*b

// int i=a+b; int i=2+2*3+6

return 0;

}

所以宏定义的计算过程定义应该用括号就要采取以下定义方式

 

#include <stdio.h>

#include "stu.h"

#include <string.h>

#define calcSum(a,b) (a)*(b)

int main(int argc, const char * argv[])

{

int i=calcSum(2+2,3+6);  

替换过程

// calcSum(a,b) a*b

// int i=a+b; int i=2+2*3+6

int k=calcSum(2+2,3)/calcSum(1, 2);

//int k=2+2*3/1*2

return 0;

}

 

但是这种定义方式还是不完美存在某些bug,所以我们应该把计算结果也用括号包住,总之我们要记住因为它只是很笨拙的做了替换操作,所以我们在使用宏定义的时候要特别小心

#define calcSum(a,b) ((a)*(b)) //最终正确定义

 

条件编译由宏定义配合,条件中不能放变量,因为变量是程序运行时才会有,而条件编译是在程序编译之前运行

#include <stdio.h>

#include "stu.h"

#include <string.h>

#define LENGTH 20

int main(int argc, const char * argv[])

{

    int k=0;

    #if LENGTH>10

    k=sum(10, 20);

    #elif LENGTH=20

    k=sumAndMin(15, 15, &k);

    #else

    k=sumNum(2, 5);

    #endif

 

    printf("%i",k);

    return 0;

}

程序性能比普通函数中的if else条件判断提高,因为以上条件编译只会编译一行代码

注意:结尾一定要写#endif因为如果没有#endif标记条件编译结束,它会一直编译到程序结尾,这样就会编译不通过,很像sqlthen else

 

是否定义宏定义作为条件编译的条件

#if defined(LENGTH)

        printf("定义了宏名为LENGTH的宏定义");

#endif

   

#if !defined(LENGTH)

    printf("没有定义了宏名为LENGTH的宏定义");

#endif

上面的判断也可以用下面的方式

#ifdef LENGTH

    printf("定义了宏名为LENGTH的宏定义");

#endif

 

#ifndef LENGTH

    printf("没有定义了宏名为LENGTH的宏定义");

#endif

Inlcude指令很像JSP中的inclue,直接把包含文件中的内容拷贝过来,我们经常会再Java项目中定义一些公共的JS文件或者我们自己开发的公共组件用include包含进来

#include <文件名>

在C语言函数头文件所在目录中找

#include "文件名"

先在程序源程序的目录中找,如果找不到,会去path(也就是系统环境变量配置的path)路径找,如果还是找不到才会去C语言函数头文件所在目录中找

可以嵌套包含,a.h包含b.h,b.h包含c.h,但是不可以递归相互包含a.h包含b.h,b.h包含a.h。

因为头文件可以嵌套包含,所以也带来了一些问题,比如头文件重复包含,这个时候我们就要使用宏定义来处理,这也是我们在XCODE中创建头文件的时候,XCODE会自动生成一段宏定义代码的原因,降低重复编译,提高效率

#ifndef testc_Student_h  //如果没有定义宏testc_Student_h

#define testc_Student_h  //定义一个宏testc_Student_h

void test();

#endif

这样不管我们的头文件被包含多少次,但是程序只会编译一次头文件中的代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值