内联函数替代有参宏

最近接到了一个老板的需求,要把我们的程序进行国际化,就是新增一个英语的支持。
大致的需求是这个样子的:程序内添加语言切换选项,并在第一次安装的时候自动选择合适的语言(中文系统的手机(无论简体中文繁体中文)一律使用简体中文,其它语言的(无论英语还是法语德语)都默认使用英文)。
其实如果只是添加多语言支持,不再应用内切换语言,苹果的开发就能很好的支持了。就是多了这个应用内切换语言(像微信那样),逻辑就复杂了很多。
因为之前的时候字符串都是写死在程序中的,所以不可能大范围的更改。又要涉及到语言的切换,所以,只能用一个折中的方法,写个宏去处理。
实现的逻辑大约是这个样子的:userdefaults存一个用户设置的语言,如果没有存储就根据系统的语言去做逻辑判断,最终得到确定使用哪种语言然后再去读取相应的语言文件,根据key-value去查找,如果查找不到就默认的使用key作为value使用了。
逻辑大约应该是这样的:

//OC
[[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",([[[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] hasPrefix:@"zh"] || ([[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] == nil && [[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] hasPrefix:@"zh"]))?@"zh-Hans":@"en"] ofType:@"lproj"]] localizedStringForKey:(key) value:key table:nil];

//swift
func L(key:String) -> String {
    var language:String? = NSUserDefaults .standardUserDefaults().objectForKey("Language") as? String
    if language == nil {
        language = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)! as? String
    }
    let bundle:NSBundle = NSBundle.init(path: NSBundle.mainBundle().pathForResource(((language!.hasPrefix("zh")) ? "zh-Hans" : "en"), ofType: "lproj")!)!
    return NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: key)
}

以上的key就是宏的形参了。

这样的宏其实是在编译之前就进行了代码的替换,其实就是把工程的所有的相关的地方替换上了这么长的代码,然后再进行编译(swift的其实是用一个public的函数去处理的,不是代码替换)。

后来发现有个更好的东西可以替换这个,就是内联函数

内联函数首先是一个函数,可以有函数的参数检查的优势

有普通的函数不具备的优势,函数的代码本质是放在符号表中的,使用的时候进行替换,没有了普通函数调用的时候的开销

执行效率和宏定义本质是一样的(内联函数是编译器首先在函数调用处使用函数体本身语句替换了函数调用语句,然后编译替换后的代码),但是还有优势

更多的内联函数的定义还是放几个博客吧:

http://blog.csdn.net/sqc3375177/article/details/8264778

http://blog.csdn.net/chsadin/article/details/47982923

http://www.cnblogs.com/QG-whz/p/4641479.html

OC的差不多这个样子写法:

static inline NSString * L (NSString * key) {
    return [[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",([[[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] hasPrefix:@"zh"] || ([[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] == nil && [[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] hasPrefix:@"zh"]))?@"zh-Hans":@"en"] ofType:@"lproj"]] localizedStringForKey:(key) value:key table:nil];
}

swift的这样就可以了

@inline(__always) func L(key:String) -> String {
    var language:String? = NSUserDefaults .standardUserDefaults().objectForKey("Language") as? String
    if language == nil {
        language = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)! as? String
    }
    let bundle:NSBundle = NSBundle.init(path: NSBundle.mainBundle().pathForResource(((language!.hasPrefix("zh")) ? "zh-Hans" : "en"), ofType: "lproj")!)!
    return NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: key)
}
@inline后面的括号里面可以有两种关键词“never”和“__always”naver是可以避免这个替代的时候使用了过大的代码块。这个到底使用普通函数还是内联函数是由编译器决定的(如果内联函数里面有循环和开关语句)就直接和普通函数没什么区别了__always其实就是程序的运行效率优先了,不管什么,直接按照内联函数对待了

总结一下,就是以后写有参宏的时候直接用内联函数就好了,写代码有提示还能尽可能的保证不出错。
时间: 2024-08-29 04:28:11

内联函数替代有参宏的相关文章

宏与内联函数

第一部分:宏 为什么要使用宏呢? 因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行.因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率.而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率. 但是宏也有很多的不尽人意的地方. 在C语言中: 1.宏容易出现一

深入探讨 内联函数和宏定义的区别

内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算求值,然后把表达式的值传递给形式参数. 内联函数与带参数宏定义的另一个区别是,内联函数的参数类型和返回值类型在声明中都有明确的指定:而带参数宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患. 使用内联函数时,应注意以下问题: 1)内联函数的定义性声明应该出现在

C/C++之宏、内联函数和普通函数的区别

内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算求值,然后把表达式的值传递给形式参数. 内联函数与带参数宏定义的另一个区别是,内联函数的参数类型和返回值类型在声明中都有明确的指定:而带参数宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患. 使用内联函数时,应注意以下问题:     1)内联函数的定义性声明应

内联函数与宏的区别

产生: 内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展:也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支.但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支. 比较: (1)宏调用并不执行类型检查,甚至连正常参数也不检查,但是函数调用却要检查. (2)C语言的宏使用的是文本替换,可能导致无法

【转】inline内联函数

技术类笔试题50%都会问宏与inline的区别,自己去找找看? 1)宏替换发生在预编译 2)宏函数(如果可以这么叫的话)替换时不会检查参数,inline函数会检查 3)宏一定会发生替换,inline貌似不是强制的,编译器想不替换也没关系 4)宏替换时存在着一些不可避免的陷阱(参见C Traps and Pitfalls),例如传参时如果传了a++之类的可能会出错,inline就比较安全了. 宏有副作用,比如MAX(x++,y++) inline会不同, 慎用内联内联能提高函数的执行效率,为什么不

内联函数知识点

内联函数知识点 1 内联函数是C++为提高程序运行速度所作的一项改进 编译器将使用相应的函数代码替换函数调用,嵌入在代码中.对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来.因此内联函数的运行速度比常规函数稍快,但代价是占用更多内存.如果程序在10给地方调用同一个内联函数,则该程序包含十个内联函数副本. 2 有选择得使用内联 a.如果执行函数代码时间比处理函数调用机制得时间长,则节约得时间将只占整个过程的一小部分. b.函数过大不使用内联,有的编译器会不能认识. 3内联函数使用方式 a.

嵌入式C语言自我修养 10:内联函数探究

10.1 属性声明:noinline & always_inline 这一节,接着讲 attribute 属性声明,attribute可以说是 GNU C 最大的特色.我们接下来继续讲一下跟内联函数相关的两个属性:noinline 和 always_inline.这两个属性的用途是告诉编译器:编译时,对我们指定的函数内联展开或不展开.它们的使用方法如下. static inline __attribute__((noinline)) int func(); static inline __att

带参宏定义和inline修饰的内联函数

带参宏定义和inline修饰的内联函数都是在编译时,用函数体替换掉宏调用或函数调用.这样用的好处是减少调用函数所花费的时间. 例如: 算法导论在讲到堆排序时说的,好的堆排序实现一般是把Left(i),Right(i),Parent(i)的实现通过宏定义或内联函数来实现,这就是因为当我们对一组数据使用堆排序时,会大量的调用left,right,parent函数定义成宏或内敛函数之后既不影响我们的代码阅读性又能是代码运行速度更快!

宏定义与内联函数

1.宏定义的规则和使用解析(1)宏定义的解析规则就是:在预处理阶段由预处理器进行替换,这个替换是原封不动的替换.(2)宏定义替换会递归进行,直到替换出来的值本身不再是一个宏为止.(3)一个正确的宏定义式子本身分为3部分:第一部分是#dedine ,第二部分是宏名 ,剩下的所有为第三部分.(4)宏可以带参数,称为带参宏.带参宏的使用和带参函数非常像,但是使用上有一些差异.在定义带参宏时,每一个参数在宏体中引用时都必须加括号,最后整体再加括号,括号缺一不可. 宏定义示例1:MAX宏,求2个数中较大的