您的位置:首页 > 编程语言 > C语言/C++

简图记录-C语言语法总结(四)预处理

2018-03-16 22:40 267 查看
简图记录学习~
一、概念
    预处理:C程序在编译过程,首先会进行预处理,包括 删除注释、递归包含#include文件、处理预处理指令、暂开宏定义。
    ANSI标准定义C语言预处理指令:

        (1)宏定义#define 撤销宏定义#undef

        (2)条件编译指令: #if 常量表达式、#ifdef 标识符、 #ifndef 标识符、#else、#elif、#endif
        (3)#error指令:编译时遇到#error error-message会产生一个编译错误提示并且停止编译,并打印出error-message

        (4)#line指令:编译时遇到 #line 行号[文件名] 会改变当前编译的行号和文件名

        (5)#pragma指令:编译遇到 #pragma 指令名  会设定编译器状态或者执行指定动作,和编译器和操作系统相关;

    常见编译宏:__LINE__行号、__FUNCTION__函数名、__FILE__文件名、__DATE__编译日期(如"25 Dec 2007")、__TIME__编译时间(如"12:30:35")
    文件包含:两种格式(1)#include <filename>到系统路径取获取文件 (2)#include "filename"先从当前目录查找,如果没有就去系统目录下;为了防止头文件被重复包含,常在.h文件用以下格式:

    
#ifndef XXXXX //常用文件名简写
#define XXXXX
/*头文件代码*/
#endif二、宏详解
    宏定义可在文件任何行定义,该文件内部从定义开始直到文件尾或者撤销定义前,都在预处理阶段展开为其定义内容。注意:(1)宏不能以分号;结尾 (2)字符串内容不会认为是宏定义进行处理 (3)注意宏处理是在 删除注释后,不要使用宏定义//等注释符号,不会得到处理;

    1、宏定义常量
         宏常用语定义常量,(1)用于定义多处使用常量,且可能需要统一修改,如#define PI 3.1415926;(2)用语提升刻度性,如错误码定义,文件路径定义。
    2、宏定义表达式

        如#define SEC_A_YEAR (60*60*24*356)UL--->考虑在16位机上可能溢出使用长整型L,且时间为无符号U

    3、宏定义宏函数(带参数表达式)

        #define AREA(a,b) ((a)*(b))--->注意一定要加括号保护、宏只是简单的提换,设想AREA(1+2,3+5);注意AREA后不能有空格,否则会认为定义AREA为(a,b) ((a)*(b))

        #define S(r) ((r)*(r))--->注意宏直接替换的特性和函数之间的差别,如S(r++)

        当进行多条语句宏命令时,运用do while(0)保护防止出错,如

        
#define CHECK_PTR(p) \
do{\
if (NULL == p){\
printf("ptr is NULL\n");\
reurn -1;
}\
}while(0);        --->设想如果没有加do wiile(0)如果使用if (...) CHECK_PTR(p);else return 0;
        几种特殊运算符宏函数:

        #define TO_STR(x) #x---->TO_STR(abc)展开为"abc"(#运算符将带参宏定义入参转化为双引号括起来的字符串)

        #define makechar(x) @#x---->makechar(a)展开为'a(#@运算符将带参宏定义单字符入参转化为单引号括起来的字符)

        #define XNAME(x) Num##x---->XNAME(9)展开为Num9(##运算符将带参宏定义参数名连接成实际参数名)

        编译上宏使用技巧:常用宏对系统函数如memset、printk、malloc等进行封装,提升代码可移植性。在特殊情况如boot下需要复用驱动代码可对驱动下特有的函数进行定义空解决编译问题。
三、pragma指令详解
    #pragam message("消息文本")--->编译时遇到进行打印

    #pragma code_seg(["段名,["段class"]])--->编译时指定代码d段

    #pragma once--->保证头文件只编译一次(兼容性不太好)

    #pragma pack(n)--->指定结构体内存对齐时,每个成员偏移为最大n倍数(当n>成员size时)

        如:#pragma pack(4)
struct test{
char a;//偏移0,占位1,b自然对齐补占位1
short b;//偏移2,占位2
int c;//偏移4,占位4
char *d;//偏移8,占位4
double e;//编译12(如果没有pack命令,自然对齐偏移应该为16保证8倍数),占位8
}
#pragma pack()//恢复默认对齐方式
/*sizeof(struct test)=20*/


        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: