今天要讲的内容是关于C语言的预处理。搞清楚了这个,就可以分析UDF中的各种头文件源代码,从此写UDF不求人。

1 关于预处理

在UDF的各种头文件中(文件路径D:\Program Files\ANSYS Inc\v180\fluent\fluent18.0.0\src),存在各种以#开头的语句,如下图中所示。



这些以#开头的语句就是C语言的预处理命令。

C语言的预处理工作由一个预处理程序来完成,任何C系统都有一个预处理程序,其负责处理源程序中的所有预处理命令,从而生成不含预处理命令的源程序。C语言的预处理目的是为了方便编程。

预处理命令以独立的预处理命令行的形式出现在源程序中,# 是其特殊的引导符号。如果源程序中某一行的第一个非空格符号是 # ,这就是一个预处理命令行。预处理命令的作用是要求预处理程序完成一些操作。

2 文件包含命令

文件包含命令是以#include开始的行,其作用是把特定文件的内容复制到当前源文件中。其存在两种形式:

# include <文件名>
# include "文件名"

两者的差异在于文件搜索方式的不同。

第一种形式,预处理程序直接到系统指定的某些目录中去查找所需文件,目录指定方式由具体系统确定,通常指定几个系统目录。

第二种形式,预处理程序现在源文件所在目录中查找,若没找到文件则再到系统指定的目录中去查找。

文件包含命令的处理过程:首先查找所需文件,找到后就用该文件的内容取代这个包含命令行。替换进来的文件中若有预处理命令,也将被处理。

3 宏定义和宏替换

#define开始的行称为宏定义命令行。宏定义包含两种形式:

  • 简单宏定义
  • 带参数宏定义

3.1 简单宏定义

简单宏定义的形式为:

#define 宏名字 替代文本

其中宏名字是任意标识符,替代文本可以是任意一段正文,其中可以包括程序中能出现的任何字符(包括空格等),一直延续到本行结束。如果需要写多行的替代文本,可以在行末写一个反斜杠\,这将使下一行内容继续被当做替代文本。

宏定义的作用就是为宏名字定义替代

如果一个宏名字的替代文本是数值或可以静态求值的表达式,当这个宏名字在程序某处出现,就相当于在那里写了这个数值或表达式。

例如,如果进行了如下定义:

#define SLD static long double

伺候,宏名字SLD就代表static long double。若程序中出现:

SLD x=2.4, y=9.16;

经过预处理后,源代码被翻译为:

static long double x=2.4,y=9.16;

预处理并不检查宏定义中的替代文本是否为合法的C语言结构,也不检查替换之后的结果是否为正确的C语言程序段,其只是简单地完成文本替换工作。

3.2 带参数的宏定义

带参数的宏定义形式为:

#define 宏名字(参数列表) 替代正文

使用带参宏时,不但要给出宏的名字,还要用类似函数实参的形式给出各宏参数的替代段,多个替代段之间用逗号分隔。这种形式也成为一个宏调用。

对宏调用的替换分两部分进行:首先用实际替代段去替换宏定义的替代正文里出现的各个宏参数,然后把替换的结果(展开后的替代正文)代入程序里出现宏调用的为准,新年广场宏替换的最后结果。

例如,定义求两个数据中较小数,可定义宏:

#define min(A,B) ((A)<(B)?(A):(B))

若程序中出现如下语句:

z = min(x+y,x*y)

则宏展开后则为:

z = ((x+y)<(x*y)?(x+y):(x*y));

带参数的宏定义与函数看起来很类似,但实际上有很大的不同。切记宏定义只是简单的文本替换。

4 条件编译命令

条件编译的作用是在源程序中划出一些片段,使预处理程序可根据条件保留或丢掉一段,或从几段中选择一段保留。实现条件编译的预处理命令有四个,分别是:

#if
#else
#elif
#endif

其中,#if#elif命令以一个能静态求出整型值的表达式为参数。另外两个没有参数。条件编译命令的常见使用形式有三种:

  • 形式一
#if 整形表达式
…… /*代码片段,条件成立时保留*/
#endif
  • 形式二
#if 整形表达式
…… /*条件成立时保留*/
#else
…… /*条件不成立时保留*/
#endif
  • 形式三
#if 整形表达式
…… /*条件成立时保留*/
#elif 整形表达式
…… /*elif部分,可以有多个*/
#elif 整形表达式
……
#else
…… /*条件都不成立时保留*/
#endif

其中整形表达式是预处理条件,值为0表示条件不成立,否则条件成立。这里常用==,!=等做判断,例如判断宏定义的符号是不是等于某个值等。

为了方便,C语言提供了一个特殊谓词defined,其使用形式有两种:

define 标识符
define (标识符)

当标识符是有定义的宏名字时,define(标识符)将得到1,否则得到0。这种表达式常被作为条件编译的条件。此外还有两个预处理命令#ifdefifndef,他们相当于#if和#define混合的简写形式。

#ifdef 标识符 /*相当于#if define(标识符)*/
#ifndef 标识符 /*相当于#if !define(标识符)*/

更多CFD资料可微信扫描下方二维码关注微信公众号。

Fluent UDF【6】:预处理命令的更多相关文章

  1. 预处理命令[#define]说明

    宏定义 宏定义是对一些常见的变量.字符串等进行定义,被定义的数据在编译会进行自动替换.有时一些变量或字符串被多次使用,当需要修改时,就需要对源文件中它们出现的地方一一修改,效率比较低,而通过宏定义,只 ...

  2. 【C语言入门教程】2.8 C 语言的预处理命令

    预处理命令是在程序编译阶段进行执行的命令,用于编译与特定环境相关的可执行文件.预处理命令扩展了 C 语言,本节将选择其中一些常用的预处理命令进行讲解. 2.8.1 宏替换命令 宏替换命令的作用类似于对 ...

  3. 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出

    [源码下载] 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 预处理命令 输入 ...

  4. 编译预处理命令--define和ifdef的使用

    这里将对常用的预处理命令进行学习. 一.宏定义  ·defined 格式:`defined     宏名      数值 或者 `define      宏名 注意:后面没有‘;‘,和单片机不一样: ...

  5. C++基础之预处理命令

    目录 概述——对预处理命令的理解 预处理命令的处理时间 C++中主要的预处理命令 宏定义 “文件包含”处理 选择编译 概述 使用C++的预处理命令可以提高程序的可维护性,有利于程序员以更加方便和快捷的 ...

  6. C/C++编译预处理命令详解【转】

    1.       预处理程序  按照ANSI标准的定义,预处理程序应该处理以下指令: #if #ifdef #ifndef #else #elif #endif #define #undef #lin ...

  7. 预处理命令#define #undef #if #endif 的基本用法

    C#的预处理命令其实还是蛮有用的,但是真正使用过得人不多,这个介绍一下平时用的比较多的预处理命令中的几个:#define,#undef ,#if,#endif.除此之外还有一些预处理命令#warnin ...

  8. c# 预处理命令

    在编译之前进行的处理. 预处理命令以符号“#”开头. #define 只能 定义符号 不能定义宏(#define PI 3.14 这是错的,在c#中没宏) #region #endregion #if ...

  9. C语言之预处理命令

    /**************************************************************************** Title:C之预处理命令 Time:201 ...

随机推荐

  1. 在CLion项目中指定不同版本的链接库

    在项目中, 需要使用到libevent-2.1.x, 但是Ubuntu16.04自带的libevent版本为2.0.5, 需要另外编译安装新版的libevent, 安装过程很简单 -stable.ta ...

  2. 解决input 有多少个radio绑定change事件,手动触发就会执行多少次问题

    如题,相信大家都会遇到这个问题,那么为什么会触发多次呢?其实当你用jquery绑定onchange事件的时候你就无形中给每个radio绑定了事件,所以才会出现执行多少次的问题了,那么如何解决呢,其实这 ...

  3. idea输入法候选区不跟随光标

    环境: win10 idea 2017.04 搜狗8.6 问题: idea编辑区输入法候选区不跟随光标 解决: 输入法改成必应输入法 不行的话不用你动手 我自砸蛋蛋.(保命狗头..)

  4. c++ remove_if

    #include <algorithm> 函数remove_if()移除序列[start, end)中所有应用于谓词p返回true的元素. 此函数返回一个指向被修剪的序列的最后一个元素迭代 ...

  5. iOS 抓取 HTML ,CSS XPath 解析数据

    以前我们获取数据的方式都是使用 AFN 来 Get JSON 数据,比如 点我查看 JSON 数据.http://news-at.zhihu.com/api/4/news/latest 但例如下面的百 ...

  6. 进阶之路(基础篇) - 019 Serial串口函数说明

    本文总结了Arduino常用串口操作函数,函数说明部分来源于Arduino 官网串口使用指南,示例与实验部分为自编.本文是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用. 函数:if( ...

  7. C++ map,set内部数据结构

    1)Set是一种关联容器,它用于存储数据,并且能从一个数据集合中取出数据.它的每个元素的值必须唯一,而且系统会根据该值来自动将数据排序.每个元素的值不能直接被改变.[重点]内部结构采用红黑树的平衡二叉 ...

  8. C结构体数组的应用

    #include <stdio.h> //定义结构体存储学生成绩信息 struct address_list{ ]; ]; ]; } info[]; void save(char *nam ...

  9. 部署hadoop的开发环境

    第一步:安装jdk 由于hadoop是java开发的,所以需要JDK来运行代码.这里安装的是jdk1.6. jdk的安装见http://www.cnblogs.com/tommyli/archive/ ...

  10. 一个MVC4 下的验证码用法

    先看一个核心验证码类(不用在意实现过程,直接copy就行),下面包含了两种验证码图片(原理一样),代码如下: using System; using System.Collections.Generi ...