C语言进阶(五):宏处理

本文详细介绍了C语言中的宏定义与使用,包括宏定义、宏常量、宏表达式及其与函数的对比。同时,讨论了条件编译的原理和用法,如#include、#error、#line、#pragma等预处理器指令,以及它们在程序开发中的作用和应用场景。
摘要由CSDN通过智能技术生成

目录

一、宏定义与使用分析

1、C语言中的宏定义

2、定义宏常量

3、宏定义表达式

4、宏表达式与函数的对比

5、宏定义的常量或表达式没有作用域限制

6、强大的内置宏

7、小结

二、条件编译使用分析

1、基本概念

2、条件编译的本质

3、#include的本质

4、条件编译的意义

5、小结

三、#error 和 #line 使用分析

1、#error的用法

2、#line的用法

3、小结

四、#pragma 使用分析

1、#pragma简介

2、#pragma message

3、#pragma once

4、#pragma pack

5、小结

五、# 和 ## 操作符使用分析

1、#运算符

2、##运算符

3、小结


一、宏定义与使用分析

1、C语言中的宏定义

  • #define预处理器处理的单元实体之一
  • #define定义的宏可以出现在程序的任意位置
  • #define定义之后的代码都可以使用这个宏

2、定义宏常量

  • #define定义的宏常量可以直接使用
  • #define定义的宏常量本质为字面量(不占用内存)

下面的宏常量定义正确吗?

#define ERROR -1
#define PATH1 "D:\test\test.c"
#define PATH2 D:\test\test.c
#define PATH3 D:\test\
test.c

int main()
{
    int err = ERROR;
    char* p1 = PATH1;
    char* p2 = PATH2;
    char* p3 = PATH3;
}

在预编译阶段(预编译 - 预处理器),程序不会报错,因为预编译器不会对语法进行检测。

实际不难发现,只有前两个是对的。

3、宏定义表达式

  • #define 表达式的使用类似函数调用
  • #define 表达式可以比函数更强大
  • #define 表达式比函数更容易出错

下面的宏表达式定义正确吗?

#include <stdio.h>

#define _SUM_(a, b) (a) + (b)
#define _MIN_(a, b) ((a) < (b) ? (a) : (b))
#define _DIM_(a) sizeof(a)/sizeof(*a)


int main()
{
    int a = 1;
    int b = 2;
    int c[4] = { 0 };

    int s1 = _SUM_(a, b);               // 1 + 2                3
    int s2 = _SUM_(a, b) * _SUM_(a, b); // 1 + 2 * 1 + 2        5
    int m = _MIN_(a++, b);              // 1 < 2 ? 2 : 2        2
    int d = _DIM_(c);                   // 16 / 4               4

    printf("s1 = %d\n", s1);
    printf("s2 = %d\n", s2);
    printf("m  = %d\n", m);
    printf("d  = %d\n", d);

    return 0;
}

4、宏表达式与函数的对比

  • 宏表达式被预处理器处理,编译器不知道宏表达式的存在

  • 宏表达式用“实参”完全替代形参,不进行任何运算

  • 宏表达式没有任何的“调用”开销

  • 宏表达式中不能出现递归定义

5、宏定义的常量或表达式没有作用域限制

下面程序合法吗?

#include <stdio.h>

void def()
{
#define PI 3.1415926
#define AREA(r) r * r * PI
}

double area(double r)
{
    return AREA(r);
}

int main()
{
    double r = area(5);

    printf("PI = %f\n", PI);
    printf("d  = 5; a = %f\n", r);

    return 0;
}

6、强大的内置宏

#include <stdio.h>
#include <malloc.h>

#define MALLOC(type, x) (type*)malloc(sizeof(type)*x)

#define FREE(p) (free(p), p=NULL)

#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s)

#define FOREACH(i, m) for(i=0; i<m; i++)
#define BEGIN {
#define END   }

int main()
{
    int x = 0;
    int* p = MALLOC(int, 5);

    LOG("Begin to run main code...");

    FOREACH(x, 5)
        BEGIN
        p[x] = x;
    END

        FOREACH(x, 5)
        BEGIN
        printf("%d\n", p[x]);
    END

        FREE(p);

    LOG("End");

    return 0;
}

7、小结

  • 预处理器直接对宏进行文本替换
  • 宏使用时的参数不会进行求值和运算
  • 预处理器不会对宏定义进行语法检查
  • 宏定义时出现的语法错误只能被编译器检测
  • 宏定义的效率高于函数调用
  • 宏的使用会带来一定的副作用
     

二、条件编译使用分析

1、基本概念

条件编译是预编译指示命令,用于控制是否编译某段代码

#include <stdio.h>

#define C 1

int main()
{
    const char* s;

#if( C == 1 )
    s = "This is first printf...\n";
#else
    s = "This is second printf...\n";
#endif

    printf("%s", s);

    return 0;
}

2、条件编译的本质

  • 预编译器根据条件编译指令有选择的删除代码
  • 编译器不知道代码分支的存在
  • if...else...语句在运行期进行分支判断
  • 条件编译指令在预编译期进行分支判断
  • 可以通过命令行定义宏
    gcc -Dmacro=value file.c   或   gcc
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值