前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >预处理

预处理

作者头像
DeROy
发布2020-05-11 11:38:06
7360
发布2020-05-11 11:38:06
举报
文章被收录于专栏:编程学习基地编程学习基地

预处理

宏定义

作用:文本替换 提高代码的可读性

代码语言:javascript
复制
1//示例 1
2#define PI 3.1415926
带参宏

没有参数类型 也没有返回值类型 可以接受任意类型的参数 本质是替换 没有任何检查

代码语言:javascript
复制
1//示例 2
2#define ADD(A,B) A+B

在示例 2 中需要考虑优先级问题

代码语言:javascript
复制
1#include<stdio.h>
2#define ADD(A,B) A+B
3int main()
4{
5    printf("%d\n",2*ADD(2,-3)); //输出结果为1
6    return 0;
7}

带参宏定义的时候加()

代码语言:javascript
复制
1//示例 3
2#define ADD(A,B) (A)+(B)

在某些特定的情况下加()也会出错

代码语言:javascript
复制
 1//示例 4 
 2//c++面试题:#define MIN(A,B) ( (A) <= (B) ? (A) : (B) )
 3#include<stdio.h>
 4#define MIN(A,B) ((A)<=(B)?(A):(B))
 5int main()
 6{
 7    int a=1,b=2;
 8    int *p=&a;
 9    printf("%d\n",MIN(*p++,b)); //结果是一个随机值
10    return 0;
11}

解释一下:

代码语言:javascript
复制
1MIN(*p++,b) = ((*p++)<(b))?(*p++):(b)
2这个表达式会产生副作用,指针p会作二次++自增操作
3开始p指向a,后来就不知道指向的是那个地址

需要注意的几点:

  • 谨记宏定义的本质是文本替换
  • 宏定义末尾没有分号
  • 宏定义一般大写表示
  • 慎用宏定义,很多坑你都找不到
特殊的宏

编译器内置的宏定义

代码语言:javascript
复制
1__LINE__    // 在源代码中插入当前源代码行号
2__FILE__    // 在源文件中插入当前源文件名
3__DATE__    // 在源文件中插入当前的编译日期
4__TIME__    // 在源文件中插入当前编译时间

这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息

代码语言:javascript
复制
 1//示例5
 2#include <stdio.h>
 3int main()
 4{
 5    printf("__FILE__:%s\n", __FILE__);    //该.c文件路径
 6    printf("__DATE__:%s\n", __DATE__);    //编译日期
 7    printf("__TIME__:%s\n", __TIME__);    //编译时间
 8    printf("__LINE__:%d\n", __LINE__);    //当前源代码行号
 9    return 0;
10}

输出结果:

代码语言:javascript
复制
1__FILE__:D:\test\test.c
2__DATE__:Dec 22 2019
3__TIME__:00:37:15
4__LINE__:7
5Press any key to continue

头文件包含

使用库函数之前,应该用#include引入对应的头文件。这种以#号开头的命令称为预处理命令。 #include<> #include" "

区别:

  • #include<>

先去系统目录中去找头文件 找不到 报错

  • #include" "

先去项目文件夹找头文件 找不到 在去系统目录找 都找不到 报错

使用注意:

系统头文件stdio.h用<>更快

自己编写的头文件用" "

条件编译

条件编译指令

说 明

#if

如果条件为真,则执行相应操作

#elif

如果前面条件为假,而该条件为真,则执行相应操作

#else

如果前面条件均为假,则执行相应操作

#endif

结束相应的条件编译指令

#ifdef

如果该宏已定义,则执行相应操作

#ifndef

如果该宏没有定义,则执行相应操作

#if-#elif-#else-#endif

#if 条件表达式1 程序段 1 #elif 条件表达式2 程序段 2 #else 程序段3 #endif

写注释的时候可以这样注释,当条件为0时代码段不编译

代码语言:javascript
复制
1#if 0
2    //代码段
3#endif
#ifndef - #define - #endif

#ifndef 标识符 #define 标识符 //… #endif 作用:防止头文件重复包含

多文件编程

代码语言:javascript
复制
 1//test.h 文件
 2#pragma once          //这个头文件只包含一次 
 3#ifndef _TEST_H_    //防止头文件重复包含
 4#define _TEST_H_
 5
 6//类型定义 函数声明 宏定义 ....
 7#include<stdio.h>
 8#define N 10
 9struct student    //结构体定义
10{
11    int data;
12};
13void fun();        //函数声明
14
15#endif 

同名.c文件

代码语言:javascript
复制
1//test.c
2#include"test.h"    //包含同名.h
3//函数定义....  放同名.c文件当中
4void fun()
5{
6    //如果要在这个里面使用其他函数  头文件放summer.h
7    printf("hello world!\n");
8}
#pragma
  • #pragma once 头文件只包含一次

在多文件编程,.h文件开头加上这段代码防止头文件重复包含

代码语言:javascript
复制
1#pragma once
  • #pragma pack(n) 结构体对齐

用n个字节作为对齐单位 n是2的x次方 1 2 4 8 16

代码语言:javascript
复制
 1//示例 6
 2#include<stdio.h>
 3typedef struct test
 4{
 5    double x;
 6    float y;
 7}TEST;
 8int main()
 9{
10    printf("size:%d\n",sizeof(TEST));
11    return 0;
12}

根据对齐规则,输出结果为:size:16

代码语言:javascript
复制
 1//示例 7
 2#include<stdio.h>
 3#pragma pack(4)        //设置结构体对齐单位为4
 4typedef struct test
 5{
 6    double x;
 7    float y;
 8}TEST;
 9int main()
10{
11    printf("size:%d\n",sizeof(TEST));
12    return 0;
13}

由于设置了对齐单位,所以输出结果为:size:12

  • 添加库 #pragma comment(lib,"winmm.lib")
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程学习基地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 宏定义
    • 带参宏
      • 特殊的宏
      • 头文件包含
      • 条件编译
        • #if-#elif-#else-#endif
          • #ifndef - #define - #endif
            • #pragma
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档