objective-c宏定义
1、先来几个常用的:
- // 是否高清屏
- #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
2、基本的使用:
- //定义π值 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
3、关于#与##的操作符:
<1>.宏定义中字符串化操作符#:
#的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号。例如
- #define WARN_IF(EXPR)\
- do {\
- if (EXPR)\
- fprintf(stderr, "Warning: " #EXPR "\n");\
- } while(0)
- 上面代码中的反斜线\主要用来转译换行符,即屏蔽换行符。
- 那么如下的代码调用:
- WARN_IF(divider == 0);
- 将被解析为:
- do {\
- if (divider == 0)\
- fprintf(stderr, "Warning: " "divider == 0" "\n");\
- } 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\n", token##N)
- int token64 = 64;
- 如下调用宏:
- PARSER(64);
- 将被解析为:
- printf("token" "64" " = %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)
4、再来个宏定义 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;
- }
5、条件编译:
- #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
6、参照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 显示编译错误信息
参考链接:http://www.uml.org.cn/c++/200902104.asp
objective-c宏定义的更多相关文章
- c++宏定义命令
在程序开始以#开头的命令,他们是预编译命令.有三类预编译命令:宏定义命令.文件包含命令.条件编译命令:今天聊聊宏定义: 宏定义命令将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来代替 ...
- dll导入导出宏定义,出现“不允许 dllimport 函数 的定义”的问题分析
建立dll项目后,在头文件中,定义API宏 #ifndef API_S_H #define API_S_H ...... #ifndef DLL_S_20160424 #define API _dec ...
- iOS之常用宏定义
下面我为大家提供一些常用的宏定义! 将这些宏定义 加入到.pch使用 再也不用 用一次写一次这么长的程序了 //-------------------获取设备大小------------------- ...
- linux中offsetof与container_of宏定义
linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->M ...
- Linux Kernel代码艺术——系统调用宏定义
我们习惯在SI(Source Insight)中阅读Linux内核,SI会建立符号表数据库,能非常方便地跳转到变量.宏.函数等的定义处.但在处理系统调用的函数时,却会遇到一些麻烦:我们知道系统调用函数 ...
- 面试问题5:const 与 define 宏定义之间的区别
问题描述:const 与 define 宏定义之间的区别 (1) 编译器处理方式不同 define宏是在预处理阶段展开: const常量是编译运行阶段使用: (2) 类型和安全检查不同 ...
- 关于Xcode8.1 / iOS10+ 真机测试系统打印或者宏定义打印不显示问题
前言: 最近做项目时遇到了很多莫名其妙的问题,其中就有这个打印(NSLog).也不多废话了,我们先来回顾一下Xcode8发布以来,我们遇到的一些关于打印的问题,当然也有解决方法: 1.Xcode8打印 ...
- JDStatusBarNotification和一些宏定义
// // AddTopicViewController.m // vMeet2 // // Created by 张源海 on 16/6/30. // Copyright © 2016年 h ...
- #define宏定义形式的"函数"导致的bug
定义了一个宏定义形式的"函数": #define SUM8(YY)\ {\ int Y = YY>>2;\ ...\ } 然后使用的时候,传入了一个同名的变量Y: i ...
- 黑马程序员——C语言基础 枚举 宏定义 自定义 static exterm
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)枚举 1)枚举类型的定义 枚举是C语言中的一种基本数据类型,并不是构 ...
随机推荐
- web安全实战
前言 本章将主要介绍使用Node.js开发web应用可能面临的安全问题,读者通过阅读本章可以了解web安全的基本概念,并且通过各种防御措施抵御一些常规的恶意攻击,搭建一个安全的web站点. 在学习本章 ...
- HDU 2340 Obfuscation(dp)
题意:已知原串(长度为1~1000),它由多个单词组成,每个单词除了首尾字母,其余字母为乱序,且句子中无空格.给定n个互不相同的单词(1 <= n <= 10000),问是否能用这n个单词 ...
- tip 2:找最小公倍数之Boost
今天在codewars上面做了一题,kata5的,其中一个实现函数是几个数字的最小公倍数.自己的代码编译虽然也成功了,但是不够简介.看了别人的代码才发现可以直接调用Boost的math模块. 看eff ...
- [ZZ+CH] Html5 canvas+js 时钟
总之新Blog入驻以后,又开始老习惯,到处折腾自定义的空间,放些东西. 想起以前大一的时候做过一个Javascript的时间显示器,现在想做一个时钟,当然现在老奸巨猾,会先去看一看有前辈写过没. 前辈 ...
- [java学习笔记]java语言基础概述之函数的定义和使用&函数传值问题
1.函数 1.什么是函数? 定义在类中的具有特定功能的一段独立小程序. 函数也叫做方法 2.函数的格式 修饰符 返回值类型 函数名(参数类型 形式参数1, 参数类型 形式参数2-) { ...
- Mac OS X开发者准备工作
迁移到Mac平台做开发后,需要有一系列的准备工作来使我们的工作更顺畅. 1. 安装Homebrew包管理器 苹果系统自带了一个包管理器,但是并不是很好用.现在,现在比较流行的是Homebrew,非常好 ...
- 修复ecshop商品重量BUG小数位增至五位
如果ECSHOP商品重量录入为1.499千克,数据库存储值为1.499:如果录入1.499克,存储值为1.显然数据保存有误差,虽然在快递运输中,此误差极小可以忽略不计,但从严谨的角度看,这是不合理的. ...
- 浏览器兼容CSS代码:按钮文字垂直居中(input button text vertical align)
经过测试的浏览器:IE6, IE7, IE8, IE9, Firefox, Chrome, Safiri, Maxthon 按钮的HTML代码: <input id="btn_comm ...
- Spark Streaming揭秘 Day34 解析UI监听模式
Spark Streaming揭秘 Day34 解析UI监听模式 今天分享下SparkStreaming中的UI部分,和所有的UI系统一样,SparkStreaming中的UI系统使用的是监听器模式. ...
- Kakfa揭秘 Day4 Kafka中分区深度解析
Kakfa揭秘 Day4 Kafka中分区深度解析 今天主要谈Kafka中的分区数和consumer中的并行度.从使用Kafka的角度说,这些都是至关重要的. 分区原则 Partition代表一个to ...