zoukankan      html  css  js  c++  java
  • C 语言宏快速入门

    //#######   参照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=2*PI*3; //效果相当于 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=2012; if(IS_LEAP_YEAR(ys)) //通常预处理程序定义在一行 如果好分行 比如说太长需要换行 需要使用“/”符号 表示还有下一行,多行分列也是如此,例: #Define IS_LEAP_YEAR year%4==0&&year%100!=0/ ||year%400==0 //宏定义参数后边放一个# 那么在调用该宏时,预处理程序将根据宏参数创建C风格的常量字符串 例: #define STR(x) # x //将会使得 随后调用的 NSLOG(STR(Programming in Objective-c./n)); //显示结果为 Programming in Objective-c./n //######### (关于 关于#与##的操作符) ######## <1>.宏定义中字符串化操作符#: #的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号。例如 #define WARN_IF(EXPR) do { if (EXPR) fprintf(stderr, "Warning: " #EXPR " "); } while(0) 上面代码中的反斜线主要用来转译换行符,即屏蔽换行符。 那么如下的代码调用: WARN_IF(divider == 0); 将被解析为: do { if (divider == 0) fprintf(stderr, "Warning: " "divider == 0" " "); } while(0); 注意能够字符串化操作的必须是宏参数,不是随随便便的某个子串(token)都行的。 <2>.宏定义中的连接符##: 连接符##用来将两个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 ", token##N) int token64 = 64; 如下调用宏: PARSER(64); 将被解析为: printf("token" "64" " = %d ", 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; }
  • 相关阅读:
    JavaScript数组去重(12种方法,史上最全转载)
    数组从大到小排序的两种方式
    jquery.inArray()和splice()使用小记
    HbuilderX 线上打包Android9.0版本无法更新
    常见的移动端H5页面开发遇到的坑和解决办法
    监听点击物理返回键及mui.fire父子页面传参
    深入理解DOM事件类型系列第三篇——变动事件
    jquery监听div等元素的内容变化
    寒假进度3
    寒假进度2
  • 原文地址:https://www.cnblogs.com/developer-ios/p/4855531.html
Copyright © 2011-2022 走看看