2

我一直在阅读有关在 iOS 中使用 #define 宏以及它们是仅在编译时运行还是在运行时运行的相互矛盾的信息。

考虑我的情况:我想定义一个宏,它返回一个与屏幕是大尺寸还是小尺寸有关的 BOOL,这里是代码:

#define TTThisScreenWidth [[UIScreen mainScreen] bounds].size.width
#define TTLargeScreenTrushHold 700.0f
#define TTScreenIsOfLargeSize (TTThisScreenWidth > TTLargeScreenTrushHold)

问题:如果此代码仅在编译时运行,则屏幕大小将在其编译到的设备上固定,并且在具有不同屏幕的设备上运行时不会返回正确答案。

但是:我检查了它,当最初为 iPhone 编译时,它在 iPad 上完美运行(通用应用程序)

SO:不安全吗?

谢谢!

4

4 回答 4

5

宏在编译时被替换;它们不在编译时运行。宏的主体将被“粘贴”来代替对宏名称的引用,就像您手动输入的一样。

通常,编译器将在编译时评估常量表达式,无论有无宏。您TTThisScreenWidth不涉及常量表达式 - 它是一个运行时表达式,因此它在运行时进行评估。

于 2012-06-28T13:10:55.793 回答
4

宏指示 C 预处理器用它的值替换它的名称。它不运行方法或函数,也不运行任何其他复杂的东西。在您的代码中,如果您TTScreenIsOfLargeSize像这样使用宏:

if (TTScreenIsOfLargeSize) {
    /* ... */
}

这实际上评估为:

if ([[UIScreen mainScreen] bounds].size.width > 700.0f) {
    /* ... */
}

因为[UIScreen mainScreen]etc.在编译时不被评估。

于 2012-06-28T13:10:48.850 回答
1

#define是用于定义常量和宏的预编译衍生词

这个怎么运作:

考虑这个例子

#define MYINT 5
#define MYSTRING @"number is %d"

在你的 .m 文件中

NSString *str = [NSString stringWithFormat:MYSTRING, MYINT];
//What really happens is
NSString *str = [NSString stringWithFormat:@"number is %d", 5];

每个定义都被它定义的值或代码替换

于 2012-06-28T13:11:34.283 回答
1

这里应该注意的是,虽然在#if、#ifdef、#endif 等情况下 C 预处理引擎有更多内容,但在指定问题的情况下,预处理引擎作为 TEXT 替换引擎工作.

这就是为什么当我们说一个人做类似的事情时:

#define varA 10
#define varB 20
#define addAB varA + varB

如果在实际编译的代码中有对 addAB 的调用,它将被替换为“varA + varB”。按照以下方式执行数学运算是并且永远是一个好习惯:

#define addAB (varA + varB)

这是为什么:如果我只是使用 addAB 的第一个定义,那么如果我做了类似的事情:

myVar = 5 * addAB;

那么文本替换引擎将使它看起来像:

myVar = 5 * varA + varB;

在编译之前。如果最初的意图是在乘法之前先将 a 和 b 相加,那么这将不是您的结果。如果改为使用第二个,则:

myVar = 5 * (varA + varB);

成为编译之前的结果表达式,这将得到你想要的。记住在这些情况下预处理器是一个简单的文本替换引擎会让你走得更远。

于 2012-06-28T14:09:14.760 回答