预处理

宏定义
预处理器直接对宏进行文本替换,宏使用时的参数不会进行求值和运算,预处理器不会对宏定义进行语法检查
#define 定义的宏可以出现在程序的任意位置
#define 定义之后的代码都可以使用这个宏(没有作用域限制)
 
#define 表达式的使用类似函数调用    #define _DIM_(a) sizeof(a)/sizeof(*a)

强大的内置宏 __FILE__ __LINE__ __DATE__ __TIME__


#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)


条件编译
实际工程中条件编译主要应用于:不同产品线共用一份代码。区分编译产品的调试版和发布版。
条件编译是预处理指令命令,用于控制是否 编译 某段代码 
预编译器根据条件编译指令有选择的删除代码
编译器不知道代码分支的存在


可以通过命令行定义宏 gcc -Dmacro=value file.c或者gcc -Dmacro file.c
/**************************************************/
#define C 1
int main()
{
#if(C == 1)
printf(" 1 \n");
#else
printf(" 2 \n");
#endif


return 0;
}
/************************************************/
int main()
{
#ifdef C
printf(" 1 \n");
#else
printf(" 2 \n");
#endif


return 0;
}
/***************************************************/
解决头文件重复包含的编译错误
#ifndef _HEADER_FILE_H_
#define _HEADER_FILE_H_

//source code

#endif
/**************************************************/
//条件编译的工程应用


//a.h
#define DEBUG 1
#define HIGH  1




//a.c
#include <stdio.h>
#include "product.h"


#if DEBUG
    #define LOG(s) printf("[%s:%d] %s\n", __FILE__, __LINE__, s)
#else
    #define LOG(s) NULL
#endif


#if HIGH
void f()
{
    printf("This is the high level product!\n");
}
#else
void f()
{
}
#endif


int main()
{
    LOG("Enter main() ...");
    
    f();
    
    printf("1. Query Information.\n");
    printf("2. Record Information.\n");
    printf("3. Delete Information.\n");
    
    #if HIGH
    printf("4. High Level Query.\n");
    printf("5. Mannul Service.\n");
    printf("6. Exit.\n");
    #else
    printf("4. Exit.\n");
    #endif
    
    LOG("Exit main() ...");
    
    return 0;
}






#error的用法
#error message   message不需要被双引号包围
#error 编译指示字用于自定义程序员特有的编译错误消息
类似的, #warning 用于生成编译警告(可以生成可执行文件,#error 不能生成可执行文件)


#ifndef __cplusplus
#error This file should be processed with C++ compiler
#endif
/***************************************************/
#include <stdio.h>


void f()
{
#if ( PRODUCT == 1 )
    printf("This is a low level product!\n");
#elif ( PRODUCT == 2 )
    printf("This is a middle level product!\n");
#elif ( PRODUCT == 3 )
    printf("This is a high level product!\n");
#else
#error the "PRODUCT " is not defined!
#endif
}


int main()
{
    f();
    
    printf("1. Query Information.\n");
    printf("2. Record Information.\n");
    printf("3. Delete Information.\n");


#if ( PRODUCT == 1 )
    printf("4. Exit.\n");
#elif ( PRODUCT == 2 )
    printf("4. High Level Query.\n");
    printf("5. Exit.\n");
#elif ( PRODUCT == 3 )
    printf("4. High Level Query.\n");
    printf("5. Mannul Service.\n");
    printf("6. Exit.\n");
#else
#error the "PRODUCT " is not defined!
#endif
    
    return 0;
}
/********************************************************/


#pragma
#pragma 用于指示编译器完成一些特定的动作
#pragma 所定义的很多指示字都是编译器特有的
#pragma 在不同的编译器是不可以移植的
预处理器将忽略他不认识的#pragma指令
一般用法 #pragma parameter

示例:
/*******************************************/
#include <stdio.h>


#if defined(ANDROID20)
    #pragma message("Compile Android SDK 2.0...")
    #define VERSION "Android 2.0"
#elif defined(ANDROID23)
    #pragma message("Compile Android SDK 2.3...")
    #define VERSION "Android 2.3"
#elif defined(ANDROID40)
    #pragma message("Compile Android SDK 4.0...")
    #define VERSION "Android 4.0"
#else
    #error Compile Version is not provided!
#endif


int main()
{
    printf("%s\n", VERSION);


    return 0;
}
/********************************************/


#pragma once
#pragma once用于保证头文件被编译一次,效率比较高,但是它是编译器相关的,不一定被支持
最佳使用方法
#ifndef _HEADER_FILE_H_
#define _HEADER_FILE_H_
#pragma once

//source code


#endif


#pragma pack













#运算符
#运算符用于预处理期间将宏参数转换为字符串
#的转换作用是在预处理期完成的,因此只在宏定义中有效
编译器不知道#的转换作用
 用法
#define STRING(x) #x
printf("%s",STRING(hello world!\n));
 工程应用
/********************************************/
#include <stdio.h>


#define CALL(f, p) (printf("Call function %s\n", #f), f(p))
   
int square(int n)
{
   return n * n;
}


int func(int x)
{
   return x;
}


int main()
{
   int result = 0;
    
   result = CALL(square, 4);
    
   printf("result = %d\n", result);
    
       result = CALL(func, 10);
   
       printf("result = %d\n", result);


   return 0;
}
/*******************************************************/




##运算符
##运算符用于在预处理器粘连两个标识符
##的转换作用是在预处理期完成的,因此只在宏定义中有效
编译器不知道##的连接作用
 用法
#define CONNECT(a,b) a##b
int CONNECT(a,1);     //int a1;
 工程应用
/****************************************************/
#include <stdio.h>


#define STRUCT(type) typedef struct _tag_##type type;\
                     struct _tag_##type


STRUCT(Student)
{
    char* name;
    int id;
};


int main()
{
    
    Student s1;
    Student s2;
    
    s1.name = "s1";
    s1.id = 0;
    
    s2.name = "s2";
    s2.id = 1;
    
    printf("s1.name = %s\n", s1.name);
    printf("s1.id = %d\n", s1.id);
    printf("s2.name = %s\n", s2.name);
    printf("s2.id = %d\n", s2.id);


    return 0;
}
/***********************************************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值