预定义符、宏函数、条件编译详解

预定义符号:

FILE //进行编译的源文件
LINE //文件当前的行号
DATE //文件被编译的日期
TIME //文件被编译的时间
STDC //如果编译器遵循ANSI C,其值为1,否则未定义。

这些预定义符号都是语言内置的。 举个例子:

 printf("file:%s line:%d\n", __FILE_, __LINE__)

宏:

define 定义标识符:
语法:

#define MAX 100

宏函数:

就是把参数替换到文本中去,这种实现方式被称为宏函数。
举个例子:

#define MUL(x ) x * x 
int a = 5;
MUL(a);// MUL(a) = MUL(5) = MUL(5) 5 * 5  = 25

但这种方式也存在着很多的问题,因为宏函数中存在着运算符优先级的“坑”。

#define MUL(x) x * x     // 方式一
#define MUL(x) (x) * (x)  //方式二
#define MUL(x) ((x) * (x))   //方式三

为什么要加这么多的括号呢?因为宏函数中存在着运算符优先级的“坑”。

int  a = 5;
//如果用方式一: 
MUL(a+1) 就会变为: 5 + 1 * 5 + 1
而根据运算符的优先级,先做乘在加 结果就会变成 5 +1 * 5+ 1 = 11
//如果用方式二呢?
MUL(a*3) = (5 * 3) * (5 * 3) = 225
只有用方式三才能避免这些潜在的“坑”,大家一定要注意。

# 和 ##

#的作用:

使用#,把一个宏参数变成对应的字符串,比如:
int i = 10; 
#define PRINT(FORMAT, VALUE)\  
printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
PRINT("%d", i+3);

代码中的#VALUE会预处理器处理为:
“VALUE” ,最终的输出的结果应该是:

  the value of i+3 is 13 

##的作用
##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。

#define ADD_TO_SUM(num, value)\
  sum##num += value; 
 ... ADD_TO_SUM(5, 10);//作用是:给sum5增加10. 

注:这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。

扫描二维码关注公众号,回复: 8864323 查看本文章

宏和函数对比

宏通常被应用于执行简单的运算。比如在两个数中找出较大的一个。

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

那为什么不用函数来完成这个任务?原因有二:

  1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹。
  2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于>来比较的类型。宏是类型无关的。
    当然和宏相比函数也有劣势的地方:
    1.每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可 能大幅度增加程序的长度。
    2.宏是没法调试的。
    3.宏由于类型无关,也就不够严谨。
    4.宏可能会带来运算符优先级的问题,导致程容易出现错。宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到。

命名约定
一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。那我们平时的一个习惯是:
把宏名全部大写
函数名不要全部大写。

条件编译

在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的。因为我们有条件编译指令。比如说:
调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译。
#include <stdio.h>
#define DEBUG

int main() 
{  
     int i = 0;  
     int arr[10] = {0}; 
     for(i=0; i<10; i++)  
   {   
     arr[i] = i;   
     #ifdef __DEBUG__   
     printf("%d\n", arr[i]);//为了观察数组是否赋值成功。 
      #endif //__DEBUG__ 
    } 
    return 0}

常见的条件编译指令:

1.
#if  常量表达式 
#endif    
//常量表达式由预处理器求值。
// 如:
#define  _DEBUG__ 1
#if __DEBUG__  //
#endif

2.多个分支的条件编译
#if 常量表达式 
//... 
#elif 常量表达式 
//... 
#else  
//... 
#endif 

3.
判断是否被定义
#if defined(symbol) 
#ifdef symbol 
#if !defined(symbol) 
#ifndef symbol 

头文件包含
如果有多个 .h文件的话,难免会出现同一个头文件被一个 .c 文件重复包含的情况。那么因该怎么避免这中状况呢?

在每一个文件的开头写:

1.
#ifndef _HEAD_H_    // 如果没有这个头文件
#define _HEAD_H_    //就定义一个这个头文件
#endif               //有的话就结束
2.
#pragma once

这样就能避免头文件的重复引用。

发布了27 篇原创文章 · 获赞 10 · 访问量 678

猜你喜欢

转载自blog.csdn.net/m1059247324/article/details/103282867
今日推荐