macro
宏只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大。
宏定义和全局变量的区别
- 宏会在预处理阶段被替换,而全局变量是在运行时;
- 宏定义不分配内存,全局变量定义需要分配内存;
- 宏不区分数据类型,它本质上是一段字符,在预处理的时候被替换到引用的位置,而全局变量区分数据类型;
- 宏定义之后值是不能改变的,全局变量的值是可以改变的;
- 宏定义只有在定义所在文件,或引用所在文件的其它文件中使用。 而全局变量可以在工程所有文件中使用,只需在使用前加一个声明。
FOUNDATION_EXTERN
#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif
由以上定义可以看出 FOUNDATION_EXTERN 是可以兼容 C++ 的 extern 的宏。
FOUNDATION_EXTERN NSString * Extern_S = @"sss";
#define Define_S @"sss"
{
NSString * s = @"tt";
CFTimeInterval begin = CACurrentMediaTime();
for (int i = 0; i < 10000; i++) {
if ([s isEqualToString:Define_S]) {
}
}
NSLog(@"%f", CACurrentMediaTime() - begin);
begin = CACurrentMediaTime();
for (int i = 0; i < 10000; i++) {
if ([s isEqualToString:Extern_S]) {
}
}
NSLog(@"%f", CACurrentMediaTime() - begin);
}
2019-09-09 16:06:04.849874+0800 Demo[86518:3255355] 0.000148
2019-09-09 16:06:04.850170+0800 Demo[86518:3255355] 0.000137
extern 比宏在字符串上的比较速度要快一些,因为 extern 直接比较指针地址,而宏是比较字符串是否相等。
__builtin_expect
这个其实是个函数,针对编译器优化的一个函数。
写代码中我们经常会遇到条件判断语句
if (今天是工作日) {
printf("好好上班");
}
else {
printf("好好睡觉");
}
CPU 读取指令的时候并非一条一条的来读,而是多条一起加载进来,比如已经加载了 if(今天是工作日) printf(“好好上班”); 的指令,这时候条件式如果为非,也就是非工作日,那么 CPU 继续把 printf(“好好睡觉”); 这条指令加载进来,这样就造成了性能浪费的现象。
__builtin_expect 的第一个参数是实际值,第二个参数是预测值。使用这个目的是告诉编译器 if 条件式是不是有更大的可能被满足。
likely 和 unlikely
解开这个宏后其实是对 __builtin_expect 封装,likely 表示更大可能成立,unlikely 表示更大可能不成立。
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
遇到这样的,if(likely(a == 0)) 理解成 if(a==0) 即可,unlikely 也是同样的。
fastpath 和 slowpath
跟上面也是差不多的,fastpath 表示更大可能成立,slowpath 表示更大可能不成立
#define fastpath(x) ((typeof(x))__builtin_expect(_safe_cast_to_long(x), ~0l))
#define slowpath(x) ((typeof(x))__builtin_expect(_safe_cast_to_long(x), 0l))
这两个理解起来跟 likely 和 unlikely 一样,只需要关注里面的条件式是否满足即可。
os_atomic_cmpxchg
其内部就是 atomic_compare_exchange_strong_explicit 函数,这个函数的作用是:第二个参数与第一个参数值比较,如果相等,第三个参数的值替换第一个参数的值。如果不相等,把第一个参数的值赋值到第二个参数上。
#define os_atomic_cmpxchg(p, e, v, m) \
({ _os_atomic_basetypeof(p) _r = (e); \
atomic_compare_exchange_strong_explicit(_os_atomic_c11_atomic(p), \
&_r, v, memory_order_##m, memory_order_relaxed); })
os_atomic_store2o
将第二个参数,保存到第一个参数
#define os_atomic_store2o(p, f, v, m) os_atomic_store(&(p)->f, (v), m)
#define os_atomic_store(p, v, m) \
atomic_store_explicit(_os_atomic_c11_atomic(p), v, memory_order_##m)
os_atomic_inc_orig
将 1 保存到第一个参数中
#define os_atomic_inc_orig(p, m) os_atomic_add_orig((p), 1, m)
#define os_atomic_add_orig(p, v, m) _os_atomic_c11_op_orig((p), (v), m, add, +)
#define _os_atomic_c11_op_orig(p, v, m, o, op) \
atomic_fetch_##o##_explicit(_os_atomic_c11_atomic(p), v, \
memory_order_##m)
UNAVAILABLE_ATTRIBUTE , __has_include
macro的更多相关文章
- FreeMarker学习(宏<#macro>的使用)
原文链接:https://my.oschina.net/weiweiblog/blog/506301?p=1 用户定义指令-使用@符合来调用 有两种不同的类型:Macro(宏)和transform( ...
- configure.ac:32: error: possibly undefined macro: AC_DEFINE
在ubuntu 下编译snappy时,在检查依赖关系时,处理autoconf的包时,在相关依赖包都已经安装的情况下,报如下错误,死活不过. configure.ac:32: error: possib ...
- 【freemaker】之自定义指令<#macro>
测试代码 @Test public void test07(){ try { root.put("name", "张三"); freemakerUtil.fpr ...
- C++ macro(宏)使用小结
谈起C++中的宏,我们第一个想到的应该就是“#define”,它的基本语法长得像这样: #define macroname(para1, para2, para3, ... ,paran) macro ...
- Macro and SQL
If you’ve developed anything in the supply chain area, you’ve most probably come across InventDimJoi ...
- The difference between macro and function I/Ofunction comparision(from c and pointer )
macro is typeless and execute faster than funtion ,becaus of the overhead of calling and returnning ...
- Cmockery macro demo hacking
/********************************************************************* * Cmockery macro demo hacking ...
- __KERNEL__ macro
转载:http://blog.csdn.net/kasalyn/article/details/17097639 The __KERNEL__ macro is defined because the ...
- 幾種方法實現C語言Macro for debug
1. #include <stdio.h> #include <stdlib.h> #define DEBUG 1 #ifdef DEBUG #define DEBUG_PRI ...
- jinja2 宏的简单使用总结(macro)
Table of Contents 1. 简介 2. 用法 3. 参数和变量 4. 注意事项 4.1. macro的变量只能为如下三种: 4.2. 和block的关系: 5. 参考文档 1 简介 ji ...
随机推荐
- node--静态文件托管,路由,模板引擎
1.路由 路由是由一个URI和一个特定的HTTP方法(GET/POST)组成的 涉及到应用如何响应客户端对某个网站节点的访问 2.ejs 3.get/post 1)get获取数据 通过Url类中的qu ...
- 使用 Hexo 创建项目文档网站
当我们发布一个开源项目的时候,最重要的事情之一就是要创建项目文档.对使用项目的用户来说,文档是非常有必要的,通常我们可以使用下面这些方式来创建文档: GitHub Wiki:在 Github 上我们可 ...
- 利用canvas绘画二级树形结构图
上周需要做一个把页面左侧列表内容拖拽到右侧区域,并且绘制成关系树的功能.看了设计图,第一反应是用canvas绘制关系线.吭哧吭哧搞定这个功能后,发现用canvas绘图,有一个很严重的缺陷.那就是如果左 ...
- Ubuntu 系统下如何安装pip3工具
一.[导读]Ubuntu 系统内置了 Python2 和 Python3 两个版本的开发环境,却没有内置相应的 pip3 管理工具,本文将介绍如何在Ubuntu下如何快速安装 pip3 工具,并升级到 ...
- python学习-练习题4巩固
一个数加100后是一个整数的平方,加268后也是一个数的平方,求这个数 分析:这个数加100之后开方是整数,说明int(math.sqrt(a+100))转为整数应该没有小数部分 so:b*b = i ...
- 以正确的方式下载和配置 ASP.NET Core 官方源码
我们可以在Github上面直接查看ASP.NET Core 3.x的源代码,但是我们也可以把源代码下载下来进行查看. 而下载源代码进行查看有很多好处: 任意的导航源代码 内置了一个示例项目 直接调试源 ...
- PDIUSBD12管脚简述
PDIUSBD12管脚简述 PDIUSBD12管脚及简述 PDIUSBD12读写时序图 CS_N是片选信号,当片选信号位低电平时,下面的操作才有效.由于板子上将CS_N接地,所以它一 ...
- C语言二进制拼接 (整数和byte类型的字符串拼接)
#include <iostream>#include <cstring>#include <cstdio> using namespace std; typede ...
- ssh 公钥 下载选择的时候 下拉选择 ssh 然后 git clone
ssh 公钥 下载选择的时候 下拉选择 ssh 然后 git clone
- $api 回调函数then应用
getReceiveListAPI (param) { return new Promise(resolve => { let params = { // idCard: this.idCard ...