首页 > 其他分享 >C语言逆向——预处理之宏定义、条件编译与文件包含

C语言逆向——预处理之宏定义、条件编译与文件包含

时间:2023-04-03 23:23:38浏览次数:37  
标签:定义 包含 int 之宏 C语言 编译 预处理 define

预处理之宏定义、条件编译与文件包含

预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理,处理后的结果再由编译器进一步编译。

预处理功能主要包括宏定义、文件包含、条件编译三部分。

宏定义

简单的宏:#define 标识符 字符序列

#define FALSE 0 #define NAME "LUODAOYI" #define __IN #define __OUT

极端例子:

#define NAME "LUODAOYI" #define A int method() { #define B char buffer[0x10]; #define C strcpy(buffer,NAME); #define D return 0;} #define E method();   // use A B C D   int main() { E return 0; }

带参数的宏:#define 标识符(参数表) 字符序列

#define MAX(A,B)((A)>(B)?(A):(B))   int method() { int x = 1; int y = 2; int z = MAX(x,y); return 0; }

多行定义,'\' 后不可有空格

#define A for(int i=0;i<length;i++)\ {\ printf("%d \n",arr[i]);\ }\   int method(int arr[],int length) { A return 0; } int main() { int arr[] = {1,2,3,4,5,6,7,8,9,0}; method(arr,10); }

直接使用宏定义函数

#define MYPRINT(X,Y) for(int i=0;i<(Y);i++)\ {\ printf("%d \n",(X)[i]);\ }\ return 0;\   int main() { int arr[] = {1,2,3,4,5,6,7,8,9,0}; MYPRINT(arr,10); }

使用宏定义函数和普通函数的区别:使用宏比较节省空间,因为使用宏定义函数,没有堆栈提升操作,也就是不会作为函数调用而是直接内联到代码内。

宏定义的注意事项

  1. 只做字符序列的替换工作,不做任何语法检测,在编译前处理

  2. 宏名标识符与左圆括号之前不允许有空白符,应紧接在一起

  3. 为了避免出错,宏定义中给形参加上括号

  4. 多行声明时,回车换行前要加上字符'\',注意字符'\'后要紧跟回车键,中间不能有空格或其他字符

  5. 末尾不需要分号

条件编译与文件包含

条件编译,就是当满足条件时才会要求编译器进行编译;如下代码当if成立则变异printf,否则就不编译:

int main() { #if 0 printf("--------") #endif return 0; }

应用场景:

#define DEBUG 0   int main() { #if DEBUG printf("--------") #endif return 0; }

可以通过反汇编代码来看一下:

images/download/attachments/12714021/image2021-3-12_0-2-7.png

可以看见printf根本没有进行编译。

if define之类的,我们都称之为预处理指令,如下是常用的。

预处理指令:条件编译是通过预处理指令实现的

指令

用途

#define

定义宏

#undef

取消已定义的宏

#if

如果给定条件为真,则编译下面代码

#endif

如果前面的#if给定条件不为真,当前条件为真,则编译下面代码

#else

同else

#endif

结束一个#if…#else条件编译块

#ifdef

如果宏已经定义,则编译下面代码

#ifndef

如果宏没有定义,则编译下面代码

#include

包含文件

文件包含

文件包含有两种格式,分别是 #include "file" 和 #include <file>

使用双引号:系统首先到当前目录下查找被包含的文件,如果没找到,再到系统指定的包含文件目录(由用户在配置环境时设置)去找
使用尖括号:直接到系统指定的包含文件目录去查找

所以系统文件用 <> 尖括号,自己定义的文件用 "" 双引号

文件包含可能会存在重复包含的情况,我们可以使用条件编译、前置声明的方式避免。

标签:定义,包含,int,之宏,C语言,编译,预处理,define
From: https://www.cnblogs.com/bonelee/p/17284878.html

相关文章

  • 【数据结构】二叉树先序、中序、后序及层次遍历(C语言版)
    一、图示展示1.先序遍历先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果先序遍历结果为:ABDHIEJCFKG动画演示:记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解2.......
  • C语言再学习 -- 详解C++/C 面试题 2
    (经典)C语言测试:想成为嵌入式程序员应知道的0x10个基本问题。参看:嵌入式程序员面试问题集锦1、用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #defineSENCONDS_PER_YEAR(60*60*24*365)UL解答:#define声明一个常量,使用计算常量表达式的值来表明一年中有多少......
  • C语言再学习 -- 输入/输出
    一、缓冲区输入字符的立即回显是非缓冲或直接输入的一个实例,它表示你说键入的字符被收集并存储在一个被成为缓冲区的临时存储区域中。按下回车可使你所键入的字符块对程序变成可用。为什么需要缓冲区?首先,将若干个字符作为一个块传输比逐个发送这些字符耗费的时间少。其次,如果你输入......
  • C语言再学习 -- 运算符与表达式
    分三部分来讲一、左值与右值参看:左值与右值首先我们需要理解左值和右值的定义:左值指的是如果一个表达式可以引用到某一个对象,并且这个对象是一块内存空间且可以被检查和存储,那么这个表达式就可以做为一个左值。      右值指的是引用了一个存储在某个内存地址里的数据。从上面......
  • C语言酒水批发管理系统[2023-04-03]
    C语言酒水批发管理系统[2023-04-03]编写一个C语言程序,实现一个酒水批发管理系统,至少能够管理30条进货/批发销售记录。其中:管理系统所管理物品仅包括各种不同品牌的酒水类货物货物信息主要包括:货物名称、货物编号、货物库存数、货物属性(不同包装、是否促销)等;进货记录主......
  • C语言文件操作
    一、为什么要使用文件我们在正常编写程序时,程序里的数据是存放在内存里的。当程序结束后,这些数据自然就不存在了。当下次运行程序的时候,数据又重新录入。而使用文件可以把数据存放到电脑里的硬盘里,这样数据就会一直存在,我们能够自己控制数据的保存与删除,做到了数据的持久化。二、什......
  • C语言逆向——switch语句中的大表和小表,本质上是内在存储空间降低
    连续值中抹去多项CPP代码:#include"stdafx.h"voidFun(intx){ switch(x){ case100: printf("100"); break; case101: printf("101"); break; case102: printf("102"); break; case106: printf("......
  • CANN训练:模型推理时数据预处理方法及归一化参数计算
    摘要:在做基于AscendCL模型推理时,通常使用的有OpenCV、AIPP、DVPP这三种方式,或者是它们的混合方式,本文比较了这三种方式的特点,并以Resnet50的pytorch模型为例,结合训练营提供的sample,说明了分别是如何实现预处理的。本文分享自华为云社区《【2023·CANN训练营第一季】——模型推......
  • C语言itoa函数
    一、atoi()函数atoi()是C语言中的字符串转换成整型数的一个函数(1)【头文件】#include<stdlib.h>(2)【函数原型】intatoi(constchar*str);(3)【函数说明】atoi()函数会扫描参数str字符串,跳过前面的空白字符(例如空格,tab缩进等),直到遇上数字或正负符号才开始做转换,而再遇到非......
  • 图像预处理
    图像预处理图像的颜色主要是由红(R)、绿(G)和蓝(B)三原色光组成。一副图像由格式为M×N×3的三维数组组成,其中的“3”可以理解为三幅M×N的二维图像(灰度值图像)。这三幅图像分别代表R、G、B分量,每个分量的像素点取值范围是[0,255]。读取的图像格式可以是png,bmp等。一、读取图......