Hello, 宏定义魔法世界

宏只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大。

宏定义和全局变量的区别

  1. 宏会在预处理阶段被替换,而全局变量是在运行时;
  2. 宏定义不分配内存,全局变量定义需要分配内存;
  3. 宏不区分数据类型,它本质上是一段字符,在预处理的时候被替换到引用的位置,而全局变量区分数据类型;
  4. 宏定义之后值是不能改变的,全局变量的值是可以改变的;
  5. 宏定义只有在定义所在文件,或引用所在文件的其它文件中使用。 而全局变量可以在工程所有文件中使用,只需在使用前加一个声明。

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的更多相关文章

  1. FreeMarker学习(宏<#macro>的使用)

    原文链接:https://my.oschina.net/weiweiblog/blog/506301?p=1 用户定义指令-使用@符合来调用  有两种不同的类型:Macro(宏)和transform( ...

  2. configure.ac:32: error: possibly undefined macro: AC_DEFINE

    在ubuntu 下编译snappy时,在检查依赖关系时,处理autoconf的包时,在相关依赖包都已经安装的情况下,报如下错误,死活不过. configure.ac:32: error: possib ...

  3. 【freemaker】之自定义指令<#macro>

    测试代码 @Test public void test07(){ try { root.put("name", "张三"); freemakerUtil.fpr ...

  4. C++ macro(宏)使用小结

    谈起C++中的宏,我们第一个想到的应该就是“#define”,它的基本语法长得像这样: #define macroname(para1, para2, para3, ... ,paran) macro ...

  5. Macro and SQL

    If you’ve developed anything in the supply chain area, you’ve most probably come across InventDimJoi ...

  6. 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 ...

  7. Cmockery macro demo hacking

    /********************************************************************* * Cmockery macro demo hacking ...

  8. __KERNEL__ macro

    转载:http://blog.csdn.net/kasalyn/article/details/17097639 The __KERNEL__ macro is defined because the ...

  9. 幾種方法實現C語言Macro for debug

    1. #include <stdio.h> #include <stdlib.h> #define DEBUG 1 #ifdef DEBUG #define DEBUG_PRI ...

  10. jinja2 宏的简单使用总结(macro)

    Table of Contents 1. 简介 2. 用法 3. 参数和变量 4. 注意事项 4.1. macro的变量只能为如下三种: 4.2. 和block的关系: 5. 参考文档 1 简介 ji ...

随机推荐

  1. Java 线程基础知识

    前言 什么是线程?线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程 ID,当前指令指针 (PC),寄存器集合和堆栈组成.另外,线 ...

  2. koa01

    1.koa简介 koa是express团队开发的一个更加轻量级的服务端开发框架,也是未来的趋势 2.安装 npm i -g koa-generator //全局安装koa脚手架 3.创建项目 koa2 ...

  3. Python-Requests库的安装和调用

    #使用pip或者pip3安装requests库pip3 install requests #requests库:python #输入python进入命令行模式在cmd命令行中依次运行以下代码,或者直接 ...

  4. 浅谈Spring框架

    一.Spring简介 Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构, 分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集 ...

  5. linux firewalld 防火墙操作命令

    查看防火墙的状态systemctl status firewalldTomcat默认使用8080端口,如果防火墙开启,需要开通8080端口firewall-cmd --zone=public --ad ...

  6. 简述树,Trie,Avl,红黑树

    树的表示方法 在平时工作中通常有2种方式来表示树状结构,分别是孩子链表示法和父节点表示法.光说名词可能无法让人联系到实际场景中,但是写出代码之后大家一定就明白了. 孩子链表示法,即将树中的每个结点的孩 ...

  7. 基于Linux Lite 4.8制作“Windows 12 Lite”正式发布

    值得注意的是,这款Windows 12 Lite的宣传标语将矛头直指Windows 10,声称不会迫使用户更新.不会存在病毒或恶意软件.启动速度比Win 10快3倍.提供8万多款优质软件.允许与Win ...

  8. R自带数据集

    向量 euro    #欧元汇率,长度为11,每个元素都有命名landmasses    #48个陆地的面积,每个都有命名precip   #长度为70的命名向量rivers   #北美141条河流长 ...

  9. JVM进阶:JVM的监控利器

    每次聊起性能测试,最后的终极话题就是怎么做优化.其实在Java的复杂项目中都会有内存不足问题.内存泄露问题.线程死锁问题.CPU问题.这些问题在小压力的情况下有可能并不明显,很容易被忽视.但是真正到了 ...

  10. element UI中的tab切换栏

    html代码:(用的是el-tab组件) <el-tabs v-model="activeIndex" type="border-card" @tab-c ...