C语言学习(4)—— 预处理指令和宏定义

一、预处理指令

预处理指令是以#号开头的代码行,#号必须是该行除了任何空白字符外的第一个字符。# 后是指令关键字,在关键字和 # 号之间允许存在任意个数的空白字符,整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换

指令含义
#空指令,没有任何效果
#include引入一个源文件
#define定义宏
#undef取消已定义的宏
#ifdef如果宏已经定义,则编译下面代码
#ifndef如果宏没有定义,则编译下面代码
#if如果给定条件为真,则编译下面代码
#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif结束一个#if.....#else条件编译块 
#include<stdio.h>

#if _WIN64          // 如果是windows平台,则执行 #include<math.h>
#include<math.h>
#elif __linux__     // 如果是linux平台,则执行 #include<string.h>
#include<string.h>
#endif

int main(){
    #if _WIN64
    double a = 2;
    printf("%f", pow(a, 3));    
    #elif __linux__     
    char *str = "C语言";
    printf("%d", strlen(str));    
    #endif

    return 0;
}

二、宏定义

#define 叫做宏定义命令,它是C语言预处理命令的一种,在编译之前就处理完成了,不占用内存。 

1. 不带参数的宏定义

宏定义就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。宏定义只是字符串替换

#define  宏名  字符串

(1)#表示这是一条预处理命令,所有的预处理命令都以#开头。

(2)宏名是标识符的一种,命名规则和变量相同,宏名为大写

(3)字符串可以是数字、表达式、if 语句、函数等,这里所说的字符串是一般意义上的字符序列,和C语言中的字符串不一样,它不需要双引号。

(4)#define在定义时没有数据类型,在参与运算时只是简单的替换。

(5)宏定义必须写在函数之外。

(6)代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替

(7)可以用宏表示数据类型,宏定义表示数据类型和用 typedef 定义数据类型的区别:宏定义只是简单的字符串替换,由预处理器来处理;而 typedef 是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型

(6)程序中反复使用的表达式就可以使用宏定义。

#include<stdio.h>

#define A  4
#define X  A
#define B  A - 2
#define C  (A - 2)
#define D  A / B * 3
#define E  A / C * 3

#define UNIT unsigned int 

int main(){
    // #define在定义时没有数据类型,在参与运算时只是简单的替换。
    printf("X = %d \n", X);   // 4
    printf("D = %d \n", D);   // A / A - 2 * 3 = -5
    printf("E = %d \n", E);   // A / (A - 2) * 3 = 6

    int F = B + E;
    printf("F = %d \n", F);   // A - 2 + A / (A - 2) * 3 = 8


    // 代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替
    printf("X \n");   // X

    // 可以用宏表示数据类型
    UNIT a = 1;      // unsigned int a = 1
    UNIT b = a + 2;
    printf("b = %d \n", b);   // b = 3

    return 0;
}

define可以配合#undef(取消定义)、#ifdef(如果定义了,必须与#endif配合使用)、 #ifndef(如果没有定义,必须与#endif配合使用)、#endif 来使用,可以让代码更加灵活

#include<stdio.h>

#define PI 3.14    
#undef PI               //取消定义
#define PI 3.1415926    //再次定义

int main(){
    #ifdef PI
        printf("PI = %f\n", PI);    // PI = 3.1415926
    #endif
    #ifndef PI
        printf("PI未定义");
    #endif

    return 0;
}

2. 带参数的宏定义

在宏定义中的参数称为“形参”,在宏调用中的参数称为“实参”,与函数有些类似,但是形参不用指明参数类型,实参需要指明参数类型。对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参

#define   宏名(形参列表)   字符串              // 注意:宏名和(形参列表)之间不能有空格

带参宏调用的一般形式为:宏名(实参列表)

字符串内的形参通常要用括号括起来以避免出错

#include<stdio.h>

#define MAX(a, b)  (a > b) ? a : b
#define SQ1(c)  c * c          // 字符串内的形参通常要用括号括起来以避免出错
#define SQ2(c)  (c) * (c)

int main(){
    int x = 2; 
    int y = 3;

    int max = MAX(x, y);       // int max = (x > y) ? x : y     不仅要进行字符串替换,还要用实参去替换形参
    printf("%d \n", max);      // 3

    int res1 = SQ1(x + 1);     // x + 1 * x + 1
    printf("%d \n", res1);     // 5  

    int res2 = SQ2(x + 1);     // (x + 1) * (x + 1)
    printf("%d \n", res2);      // 9  

    return 0;
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值