【问题标题】:Objective-C #define macro evaluation incorrect within if statementObjective-C #define 宏评估在 if 语句中不正确
【发布时间】:2013-10-29 18:16:46
【问题描述】:

我很困惑为什么在以下 if 语句中使用以下 #define 宏时未按预期进行评估:

#define kOffsetX  2048.0
#define kPositionX (screenSize.width * (kOffsetX/2048.0))-10.0

CGSize screenSize = [CCDirector sharedDirector].winSize;
float potentialPosition = 486.86f;
float playersFieldOffset = 1.0;

if ((potentialPosition - kPositionX) * playersFieldOffset > 0.0) {

请注意,kPositionX 的计算结果为 470.0。当 486-470 明显大于零时,if 语句的计算结果为 FALSE。但是,如果我在 kPositionX 周围加上括号,则 if 语句正确地计算为 TRUE。

为什么会这样?这是使用#define 的不当方式吗?如果是这样,我该怎么办?

【问题讨论】:

    标签: objective-c macros c-preprocessor


    【解决方案1】:

    预处理器只是用它们的定义替换所有宏,所以

    potentialPosition - kPositionX
    

    扩展为

    potentialPosition - (screenSize.width * (2048.0/2048.0))-10.0
    

    在运行时评估时给出

    486.86 - 480 - 10  = -3.14 < 0
    

    您应该始终将宏中的表达式括在括号中:

    #define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)
    

    所以展开式给出

    potentialPosition - ((screenSize.width * (2048.0/2048.0))-10.0)
    

    这是你所期望的。

    这是预处理器宏的(之一)缺点。或者,您可以 使用例如(内联)函数,请参阅Inline functions vs Preprocessor macros 了解更多信息。

    【讨论】:

      【解决方案2】:

      每当使用#define 时,请确保将#define 的全部内容括在括号中。这将防止发生任何不正确的操作计算顺序。因此,将您的#defines 更改为

      #define kOffsetX  (2048.0)
      #define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)
      

      【讨论】:

        【解决方案3】:

        #define 宏是文字表达式!在拼接任何参数之后(并且您没有为该宏使用任何参数),该宏基本上直接插入到代码中。所以,当你期待的时候

        if ((potentialPosition - kPositionX) * playersFieldOffset &gt; 0.0)

        变成

        if ((potentialPosition - (answer of kPositionX) * playersFieldOffset &gt; 0.0)

        其实变成了

        if ((potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0) * playersFieldOffset &gt; 0.0)

        评估不正确。您可以通过将整个宏括在括号中来解决此问题。

        #define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)

        或者,如你所说,用括号括住 kPositionX

        if ((potentialPosition - (kPositionX)) * playersFieldOffset &gt; 0.0) {

        此外,作为良好实践的一般规则,宏通常全部大写,下划线 (_) 表示单词之间的分隔符。 #define MACRO_NUMBER_ONE

        【讨论】:

          【解决方案4】:

          宏通过字符串替换工作。您的宏 kPositionX 的形式为 (a) - b,因此当您在子表达式 (potentialPosition - kPositionX) 中使用它时,结果为:

          (potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0)
          

          其中10.0potentialPosition减去。可能你想要:

          (potentialPosition - ((screenSize.width * (kOffsetX/2048.0)) - 10.0))
          

          注意额外的括号 - 其中10.0添加potentialPosition

          您必须始终记住,宏在定义宏时使用字符串替换,并且任何包含表达式的宏都应该有外括号以避免出现问题:

          #define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)
          

          【讨论】:

            猜你喜欢
            • 2016-05-17
            • 1970-01-01
            • 1970-01-01
            • 2010-12-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多