//#######   参照C语言的预处理命令简介  ########

#define              定义一个预处理宏
#undef 取消宏的定义
#include 包含文件命令
#include_next 与#include相似, 但它有着特殊的用途
#if 编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef 与#ifdef相反, 判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用, 判断某个宏是否被定义
#line 标志该语句所在的行号
# 将宏参数替代为以参数值为内容的字符窜常量
## 将两个相邻的标记(token)连接为一个单独的标记
#pragma 说明编译器信息
#warning 显示编译警告信息
#error 显示编译错误信息 //######## 条件编译 ####### #if !defined(FCDebug) || FCDebug == 0
#define FCLOG(...) do {} while (0)
#define FCLOGINFO(...) do {} while (0)
#define FCLOGERROR(...) do {} while (0) #elif FCDebug == 1
#define FCLOG(...) NSLog(__VA_ARGS__)
#define FCLOGERROR(...) NSLog(__VA_ARGS__)
#define FCLOGINFO(...) do {} while (0) #elif FCDebug > 1
#define FCLOG(...) NSLog(__VA_ARGS__)
#define FCLOGERROR(...) NSLog(__VA_ARGS__)
#define FCLOGINFO(...) NSLog(__VA_ARGS__)
#endif //############## 适配宏 ################ // 是否高清屏
#define isRetina ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO)
// 是否模拟器
#define isSimulator (NSNotFound != [[[UIDevice currentDevice] model] rangeOfString:@"Simulator"].location)
// 是否iPad
#define isPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// 是否iPad
#define someThing (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)? ipad: iphone //##############基本使用################ //定义π值 3.1415926
#define PI 3.1415926
//则在程序用可以如下使用
double i=*PI*;
//效果相当于 double i=2*3.1415926*3; //预处理命令可以定义任何符合格式的形式,例如判断年份是否闰年
#define IS_LEAP_YEAR year%4==0&&year%100!=0||year%400==0
//使用时则可以直接
if(IS_LEAP_YEAR) //或者可以定义一个参数
#define IS_LEAP_YEAR(y) y%4==0&&y%100!=0||y%400==0
//使用时则可以直接
int ys=;
if(IS_LEAP_YEAR(ys)) //通常预处理程序定义在一行 如果好分行 比如说太长需要换行 需要使用“/”符号 表示还有下一行,多行分列也是如此,例:
#Define IS_LEAP_YEAR year%==&&year%!=/
||year%==
//宏定义参数后边放一个# 那么在调用该宏时,预处理程序将根据宏参数创建C风格的常量字符串 例:
#define STR(x) # x
//将会使得 随后调用的 NSLOG(STR(Programming in Objective-c./n));
//显示结果为 Programming in Objective-c./n //######### (关于 关于#与##的操作符) ######## <>.宏定义中字符串化操作符#:
#的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号。例如 #define WARN_IF(EXPR)\
do {\
if (EXPR)\
fprintf(stderr, "Warning: " #EXPR "\n");\
} while() 上面代码中的反斜线\主要用来转译换行符,即屏蔽换行符。 那么如下的代码调用:
WARN_IF(divider == ); 将被解析为:
do {\
if (divider == )\
fprintf(stderr, "Warning: " "divider == 0" "\n");\
} while(); 注意能够字符串化操作的必须是宏参数,不是随随便便的某个子串(token)都行的。 <>.宏定义中的连接符##:
连接符##用来将两个token连接为一个token,但它不可以位于第一个token之前or最后一个token之后。注意这里连接的对象只要是token就行,而不一定是宏参数,但是##又必须位于宏定义中才有效,因其为编译期概念(比较绕)。 #define LINK_MULTIPLE(a, b, c, d) a##_##b##_##c##_##d
typedef struct _record_type LINK_MULTIPLE(name, company, position, salary);
/*
* 上面的代码将被替换为
* typedef struct _record_type name_company_position_salary;
*/ 又如下面的例子:
#define PARSER(N) printf("token" #N " = %d\n", token##N) int token64 = ; 如下调用宏:
PARSER(); 将被解析为:
printf("token" "" " = %d\n", token64); 在obj-c中,如果我有如下定义:
#define _X(A, B) (A#B)
#define _XX(A, B) _X([NSString stringWithFormat:@"%@_c", A], B)
gcc将报错!
正确的写法为:
#define _XX(A, B) _X(([NSString stringWithFormat:@"%@_c", A]), B) //######## 宏的object-c 单例 ###### #define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_)
static _object_name_ *z##_shared_obj_name_ = nil;
+ (_object_name_ *)_shared_obj_name_ {
@synchronized(self) {
if (z##_shared_obj_name_ == nil) {
/* Note that ‘self’ may not be the same as _object_name_ */
/* first assignment done in allocWithZone but we must reassign in case init fails */
z##_shared_obj_name_ = [[self alloc] init];
_GTMDevAssert((z##_shared_obj_name_ != nil), @”didn’t catch singleton allocation”);
}
}
return z##_shared_obj_name_;
} + (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (z##_shared_obj_name_ == nil) {
z##_shared_obj_name_ = [super allocWithZone:zone];
return z##_shared_obj_name_;
}
} /* We can’t return the shared instance, because it’s been init’d */
_GTMDevAssert(NO, @”use the singleton API, not alloc+init”);
return nil;
} - (id)retain {
return self;
} - (NSUInteger)retainCount {
return NSUIntegerMax;
} - (void)release {
} - (id)autorelease {
return self;
} - (id)copyWithZone:(NSZone *)zone {
return self;
}

C 语言宏快速入门的更多相关文章

  1. 学习swift语言的快速入门教程推荐

    随着苹果产品越来越火爆,苹果新推出的swift必定将在很大程度上代替oc语言.学好swift语言,对于IOS工程师来讲,已经是一门必备技能. 有一些比较好的英文版教程,值得学习. 1. Swift T ...

  2. 最近一些朋友问我,临近快毕业了专业不对口,想转行看到IT行业就业前景不错,但是编程语言众多不了解,不知道哪门语言能够快速入门掌握,短期能让我找到工作

    我做互联网前端后台开发也有四年多了,一路走过来,累并快乐着.快乐比艰辛更多,源自我的兴趣驱动.初中的一个偶然的机会我接触到了计算机,从那个时候就喜欢上开始经常到网吧上网.那个时候我对计算机领域的认识是 ...

  3. c语言快速入门3

    如果你想快速入门计算机,可以参考我的上一篇帖子,先了解一些必备的软知识,然后再来进行语言的快速入门 计算机入门基础知识 c语言快速入门1 c语言快速入门2 3.4.1 字符和字符串 字符:'' 单个  ...

  4. c语言快速入门2

    如果你想快速入门计算机,可以参考我的上一篇帖子,先了解一些必备的软知识,然后再来进行语言的快速入门 计算机入门基础知识 c语言快速入门1 1.1.12 函数的概念 函数的定义:c语言的基本单位,c语言 ...

  5. c语言快速入门1

    如果你想快速入门计算机,可以参考我的上一篇帖子,先了解一些必备的软知识,然后再来进行语言的快速入门 计算机入门基础知识 目录 1.1.1    计算机与程序 现代计算机可以自动完成计算任务 程序就是按 ...

  6. [易学易懂系列|rustlang语言|零基础|快速入门|(22)|宏Macro]

    [易学易懂系列|rustlang语言|零基础|快速入门|(22)|宏Macro] 实用知识 宏Macro 我们今天来讲讲Rust中强大的宏Macro. Rust的宏macro是实现元编程的强大工具. ...

  7. 如何快速入门单片机C语言

    一.为什么要学单片机技术? 传统的电子产品升级改造成智能化的电子产品需要用到单片机技术.也就是说传统的电子产品如电视机.电子表.计算器.数码相机.手机.MP3.遥控器.洗衣机等产品智能化.微型化,需要 ...

  8. [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)]

    [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)] 项目实战 实战2:命令行工具minigrep 我们继续开发我们的minigrep. 我们现 ...

  9. [易学易懂系列|rustlang语言|零基础|快速入门|(20)|错误处理]

    [易学易懂系列|rustlang语言|零基础|快速入门|(20)|错误处理] 实用知识 错误处理 我们今天来讲讲Rust中的错误处理. 很多语言都有自己的错误处理方式,比如,java是异常处理机制. ...

随机推荐

  1. System.err与System.out的区别

    大多数操作系统都有三个标准文件描述符:标准输入,标准输出,标准出错. 三个操作系统的文件描述符映射到编程语言的标准库中,往往加了一层包装,但是名字通常还是叫标准输入,标准输出,标准出错. 在其它语言中 ...

  2. Jenkins系列之Jenkins的安装(一)

    自动化测试的时候通常我们都会进行持续集成,下面是持续集成工具Jenkins的安装 Jenkins优点: 开源免费 跨平台,支持所有的平台 web形式的可视化的管理页面 安装配置超级简单 tips及时快 ...

  3. sql常用手法(二)

    drop,TRUNCATE和delete的区别 1.DROP删表,表结构将删了,当然数据也不存在了2.TRUNCATE和DELETE删数据,表结构还在3.DELETE可以带条件删除,TRUNCATE是 ...

  4. linux mysql设置远程访问

    >mysql -u root -p 选择进入mysql数据库use `mysql`; 查看所有存在的账号和地址.SELECT `Host`,`User` FROM `user`; 现在决定让ro ...

  5. docker 转载

    写的非常好的一篇文章,不知道为什么被删除了.  利用Google快照,做个存档. 快照地址:地址 作者地址:青牛 什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 do ...

  6. Python基础之字符的编码

    参考原文 Python廖雪峰 为什么要进行编码? 计算机只能处理二进制数字(0100111),要处理文本,就必须先把文本转为数字才能处理,这个过程就叫编码. 字符的编码 ASCII编码 由于计算机是美 ...

  7. 在PL/SQL DEV里面有把锁一样的按钮,点击它会跳出“these query result are not updateable,include the ROWID to get updateab

    在PL/SQL DEV里面有把锁一样的按钮,点击它会跳出“these query result are not updateable,include the ROWID to get updateab ...

  8. Linux学习笔记记录(二)

  9. 第八节:web爬虫之urllib(四)

    第三个 模块parse : 是一个工具模块,提供了许多 URL 处理方法,比如拆分.解析.合并等等的方法.

  10. lua排序算法

    SEED = ; --随机序列 可任取 NUM = ; --排序规模 --随机序列 初始数据 function GenRnd( seed, n ) --生成随机数 data = {}; local r ...