C语言进阶(预处理命令详解)

2025-07-25 20:50

本文主要是介绍C语言进阶(预处理命令详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块...

1.宏定义

1.1不带参宏

#define  PI   3.14

变量名尽量大写

1.2带参宏

定义方式:

#defjsine  MAX(x, y)     x > y ? x : y

下面的代码运行结果为15,显然是错误的。

   #include <stdio.h>
   #define JISUAN(x, y, z)    x * y + z
   int main(void)
   {
       int a = 0;                                                      php   www.chinasem.cn                                                                                        
       a = JISUAN(1 + 2,2 * 3,3 - 1);
       printf("%d",a);
   }     

给变量带上括号,运行结果是,正确做法如下:运行结果为20。因此尽量给定义添加括号。避免计算错误。

   #include <stdio.h>
   #define JISUAN(x, y, z)    ((x) * (y) + (z))
   int main(void)
   {
       int a = 0;                                                                                                                                                 
       a = JISUAN(1 + 2,2 * 3,3 - 1);
       printf("%d",a);
   }     

带参宏和函数的区别:

带参宏函数
带参宏没有参数类型、返回值、函数类型 相关概念函数有参数类型、函数类型、返回值相关 概念
带参宏只是代码的替换,没有调用传参过 程函数有调用、传参过程
带参宏是在程序编译时展开,代码体积增 大函数是在程序运行过程中加载,代码体积 不会增大
带参宏没有传参过程,执行效率高函数有传参过程,需要调用、传参产生资 源开销
简单的代码想要封装模块,优先带参宏需要严谨的代码逻辑,多行代码,考虑使 用函数

2.头文件的包含

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "head.h"

#include 包含一个文件,文件会在预处理编译时展开。

<>:在系统目录下查找该头文件。

"":在当前目录下查找该头文件,如果找不到再到系统目录下查找头文件。

2.1头文件中的内容

1.构造数据类型的定义

2.全局变量的声明

3.全局函数的声明

4.宏定义

2.2工程结构

C语言进阶(预处理命令详解)

main.c中负责主函数编写

  • 功能代码.c中主要负责功能函数的编写
  • 功能代码.h中主要负责声明功能代码.c中编写的功能函数
  • 调用函数的文件只需加对应函数的.h头文件即可使用该函数

这么说可能有些不太好理解,我们来举个例子吧:

我们先创建一个工程文件夹jisuan来进行输入两个数字的四则运算:

C语言进阶(预处理命令详解)

再在里面创建jia.c jia.h jian.c jian.h cheng.c cheng.h chu.c chu.h main.c,一个.c的功能文件必须对应一个.h的头文件声明用来方便主文件的调用!这里main.c不需要头文件。因为这里存放主函数。

C语言进阶(预处理命令详解)

创建好后分别对jia.cjian.c cheng.c chu.javascriptc函数进行编写。

  • jia.c:
   #include<stdio.h>
   float jia(float x , float y)                                                                                                                                                     
         {
             return x + y;
         }
  • jian.c:
  #include <stdio.h>
   float jian(float x , float y)
         {
             return x - y;                                                                                                                                                          
         }
  • cheng.c:
  #include<stdio.h>                                                                                                                                                                
   float cheng(float x , float y)
         {
             return x * y;
         }
  • chu.c:
   #include<stdio.h>
   extern float chu(float x , float y)                                                                                                                                              
         {
             return x / y;
         }

接下来依次编写他们的头文件:

  • jia.h
 extern float jia(float x ,float y); 

jian.h

 extern float jian(float x ,float y); 
  • cheng.h
 extern float cheng(float x ,float y); 
  • chu.h
 extern float chu(float x ,float y); 

最后我们进行主函数的编写:这里要注意一定要用#include"函数功能.h"来声明定义的变量

  • main.c:
   #include<stdio.h>
   #include"jia.h"
   #include"jian.h"
   #include"cheng.h"
   #include"chu.h"
   
   int main(void)
   {
       float r1 = 0;
      float r2 = 0;
      float r3 = 0;
      float r4 = 0;
      float a = 0;
      float b = 0;
      scanf("%f %f",&a,&b);
      r1 = jia(a,b);
      r2 = jian(a,b);
      r3 = cheng(a,b);
      r4 = chu(a,b);
      printf("jia = %f\n",r1);
      printf("jian = %f\n",r2);
      printf("cheng = %f\n",r3);
      printf("chu = %f\n",r4);
      return 0;
  }  

ok,编写工作完成,我们来对.c文件进行编译:

C语言进阶(预处理命令详解)

编译完成后就会出现一个可执行文件main

C语言进阶(预处理命令详解)

我们试着运行一下:

C语言进阶(预处理命令详解)

输入12和45,得出计算结果。

这里,我在想这不是跟我前一篇写的函数里extern外部声明一样的嘛,只不过通过#include""展开函数声明而已。但是在未来的项目中撰写每个功能代码和主函数的不是同一个人,为了方便撰写主函数的人调用,采用这样的方法是不错的选择。

3.条件编译

关键字功能描述
#if如果条件为真则编译后续代码块
#elif若前面的#if或#elif条件不成立,并且该条件成立,则编译该部分的后续代码块
#else若前面的#if和#elif都不成立,则编译该部分代码块
#endif结束一个条件编译块,必须要与#if,#ifdef,#ifndef联用
#ifdef若某个宏被定义,则使用该部分代码
#ifndef若某个宏没被定义,则使用该部分代码
#if 1
编译此部分
#elif 
不编译该部分
#else
#if 0
不编译该部分
#elif 1
编译该部分
#else
test
#if 0
不编译该部分
#elif 0
不编译该部分
#else
编译该部分
#if 1
编译该部分
#endif  结束此条件编译
#if 0
不编译该部分
#endif  结束此条件编译

#ifdef与#ifndef一般在项目测试中使用,可以在编译时http://www.chinasem.cn于外部定义或不定义某个宏,以此来调用代码。

  #include <stdio.h>
  #define JISUAN(x, y, z)    ((x) * (y) + (z))
  int main(void)
  {
      #ifdef  TEST
      printf("测试\n");
      #endif
      #ifdef  YINGYONG
      printf("应用\n");
      #endif
      return 0;
  } 

如上述代码,对其编译gcc -D TEST l.c -o l 在编译的时候在外部定义了TEST,则输出测试

C语言进阶(预处理命令详解)

如果在外部定义YINGYONG 则输出应用。

C语言进阶(预处理命令详解)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于C语言进阶(预处理命令详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155485

相关文章

Redis 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MySQL8 密码强度评估与配置详解

《MySQL8密码强度评估与配置详解》MySQL8默认启用密码强度插件,实施MEDIUM策略(长度8、含数字/字母/特殊字符),支持动态调整与配置文件设置,推荐使用STRONG策略并定期更新密码以提... 目录一、mysql 8 密码强度评估机制1.核心插件:validate_password2.密码策略级

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

详解python pycharm与cmd中制表符不一样

《详解pythonpycharm与cmd中制表符不一样》本文主要介绍了pythonpycharm与cmd中制表符不一样,这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽... 这个问题通常是因为PyCharm和命令行(CMD)使用的制表符(tab)的宽度不同导致的。在PyChar