在“if”语句中使用#define

5

在“if”语句中使用#define是否可行?以下代码可以工作,但我收到了一个警告,表示正在重新定义宏。

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
 #define TableViewHeight 916
 #define DisplayHeight 1024
 #define DisplayWidth 768
}
else {
 #define TableViewHeight 374
 #define DisplayHeight 480
 #define DisplayWidth 320
}

我也尝试过这个方法,但是它没有生效:

#ifdef UIUserInterfaceIdiomPad
 #define TableViewHeight 916
 #define DisplayHeight 1024
 #define DisplayWidth 768
#else
 #define TableViewHeight 374
 #define DisplayHeight 480
 #define DisplayWidth 320
#endif

有什么想法吗?

1
在我看来,这不是常量的设计初衷。 - surfasb
6个回答

7

是的,这是可能的,但它可能不会做你想要的事情。预处理器指令在编译预处理步骤的结果之前被解释。

这意味着在剩余代码被编译之前,所有预处理器指令都被解释,重新定义一些宏,而剩余代码将类似于以下内容。

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
}
else {
}

换句话说,预处理后,你只剩下空的ifelse体。
如果你想在运行时根据条件更改某个值,那这个值就必须是一个真正的对象,而不仅仅是一个预处理器宏。例如:
extern int TableViewHeight; // defined somewhere else
extern int DisplayHeight; // defined somewhere else
extern int DisplayWidth; // defined somewhere else

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  TableViewHeight = 916;
  DisplayHeight = 1024;
  DisplayWidth = 768;
}
else {
  TableViewHeight = 374;
  DisplayHeight = 480;
  DisplayWidth = 320;
}

1
所有四个答案都是事实正确的,但这是唯一一个真正解释了正确方法的答案。 - Chuck

1

#define(以及#ifdef等)是由预处理器处理的。这完全在编译器本身之前运行;它们实际上是两个完全独立的进程。因此,它根本不与if等结构交互。

如果UIUserInterfaceIdiomPad是一个宏(即已经被#defined),则您的第二个代码示例可能有效。


1

我想你已经回答了自己的问题 :) 但是,为了消除警告,为什么不将它们声明为变量而不是宏呢?

我会这样做:

CGFloat tableHeight = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 916.0f : 374.0f;

1

#defines在编译器运行之前被预处理器替换。意味着你不能在运行时设置它们的值。我可能会以这样的方式来实现你想要的效果:

在你的.h文件中:

static CGFloat TableViewHeight;
static CGFloat DisplayHeight;
static CGFloat DisplayWidth;

在 .m 文件中(类的实现):

+ (void)initialize
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
     TableViewHeight = 916.0;
     DisplayHeight = 1024.0;
     DisplayWidth = 768.0;
    } else {
     TableViewHeight = 374.0;
     DisplayHeight = 480.0;
     DisplayWidth = 320.0;
    }
}

或者,你可以像这样做:

#define TableViewHeight ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 916.0 : 374.0)
#define DisplayHeight ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 1024.0 : 480.0)
#define DisplayWidth ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 768.0 : 320.0)

最后,对于DisplayHeight和DisplayWidth,您实际上不需要执行任何操作,最好使用CGRectGetHeight([[UIScreen mainScreen] bounds])CGRectGetWidth([[UIScreen mainScreen] bounds])

0

使用#if而不是普通的if

然而这将是一个预处理器的事情,这意味着您的应用程序只能编译为iPhone或iPad(如果它甚至工作)。

底线:不,您不能使用宏。它们在编译时被检查,而不是在运行应用程序时。


0
很遗憾,#define被预处理器用于在代码编译之前替换符号,而if是要编译的实际代码的一部分。在第一种情况下,预处理器不知道您的if语句的结果是什么。
第二种情况没有意义,因为您不关心UIUserInterfaceIdiomPad是否被定义,而是关心UI_USER_INTERFACE_IDIOM()是否具有该值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接