【问题标题】:What is the precedence of operators in C# Preprocessor Directives?C# 预处理器指令中运算符的优先级是什么?
【发布时间】:2014-08-11 13:21:55
【问题描述】:

如果我有一段用 C# 编写的代码包含在 #if 指令中,那么该指令中可能使用的任何布尔运算符应用什么(如果有)优先级?

换句话说:

#if DEBUG || MYTEST && PLATFORM_WINDOWS
// ... Some code here
#endif

这会被简单地从左到右评估为

#if (DEBUG || MYTEST) && PLATFORM_WINDOWS

同样,会

#if PLATFORM_WINDOWS && DEBUG || MYTEST

被评价为

#if (PLATFORM_WINDOWS && DEBUG) || MYTEST

或者 && vs || 有什么优先顺序?

编辑:明确地说,我很清楚我可以自己运行代码来测试它,而且我已经做到了。我正在寻找一个能给我一些官方信息的答案——参考文档等,这可以让我更深入地了解指令的底层机制。我想知道是否有特定的预期行为,或者这是否纯粹是未定义的。

【问题讨论】:

  • 无论如何都应该使用 IMO 括号,以避免思考开销和这种混乱
  • 为什么不运行一些测试并告诉我们?这是您自己很容易发现的。
  • @BobHorn 从我的测试中可以看出,它是从左到右评估的。但是,我正在寻找一个更官方的答案(最好是指向一些官方文档的东西)以获得更完整的理解。我自己的测试很好,但很高兴知道我的发现是预期的行为,还是只是恰好现在以这种方式工作的未定义的东西。
  • 你已经有了代码。你只需要执行它。这样做会比你花在写这个问题上的时间远远少。
  • @Mehrdad 这不是弄清楚我的程序中发生了什么,这很简单(如上所述,我总是添加括号来澄清评估顺序)。我正在寻找更正式的东西,以更好地理解指令的基本机制。

标签: c# c-preprocessor operator-precedence


【解决方案1】:

我相信 && 运算符的优先级高于 || C# 中的运算符,如下所示,http://msdn.microsoft.com/en-us/library/aa691323(v=vs.71).aspx

因此您的代码将被评估:

#if DEBUG || MYTEST && PLATFORM_WINDOWS
// ... Some code here
#endif

将被评估为

#if (MYTEST && PLATFORM_WINDOWS) || DEBUG
// ... Some code here
#endif

【讨论】:

  • 这适用于 C# 表达式(以及大多数其他语言),但我无法找到明确声明这适用于 C# preprocess 条件的参考。显示实际测试结果将为声明添加证据,找到官方参考/规范,更是如此。
  • @user2864740 这正是 OP 被要求在 cmets 中针对这个问题做的事情!
【解决方案2】:

请参阅 C# 语言规范版本 5.0 中的 2.5.2 预处理表达式

规范没有讨论运算符优先级,但它遵循该部分中给出的 BNF 语法。

  1. 括号、常量(truefalse)和条件符号(PLATFORM_WINDOWSDEBUG 等)
  2. 一元!
  3. 平等==, !=
  4. 还有&&
  5. ||

它还说:

在预处理表达式中引用时,已定义的条件编译符号具有布尔值 true,而未定义的条件编译符号具有布尔值 false。

预处理表达式的求值总是产生一个布尔值。预处理表达式的求值规则与常量表达式的求值规则(第 7.19 节)相同,但唯一可以引用的用户定义实体是条件编译符号。

【讨论】:

  • 关于该引文的最后一段,实际上它的意思是,虽然#if FOO == FOO 始终为 true,但这只是因为在这种特殊情况下,条件(“FOO 是(未)定义”)将总是等于条件(“FOO 是(未)定义”)。然而,要看到这些“变量”没有正确的身份,只需考虑如果“BAR”也恰好是“定义的”,那么FOO == BAR 也是正确的。相反,FOO != BAR 在两者处于相反的“已定义”状态时占主导地位,true/falsefalse/true
【解决方案3】:

预处理器指令中的优先级与usual precedence 相同:&& 的优先级高于||。为了演示这一点,运行以下代码:

#undef A
#define B
#define C
#if A && B || C
    Console.WriteLine(1);
#endif
#if (A && B) || C
    Console.WriteLine(2);
#endif
#if A && (B || C)
    Console.WriteLine(3);
#endif
#if B || C && A
    Console.WriteLine(4);
#endif
#if B || (C && A)
    Console.WriteLine(5);
#endif
#if (B || C) && A
    Console.WriteLine(6);
#endif

输出是:

1
2
4
5

这表明括号在 && 周围时是等效的,而不是在左侧的两项。

【讨论】:

    【解决方案4】:

    2.5.2 预处理表达式

    预处理表达式的求值总是产生一个布尔值 价值。 预处理表达式的求值规则是 与常量表达式(第 7.19 节) 相同,除了唯一的 可以引用的用户定义实体是有条件的 编译符号

    7.19 常量表达式

    常量表达式的编译时求值使用与非常量表达式的运行时求值相同的规则*,除了运行时求值会抛出异常的地方,编译时评估会导致发生编译时错误。

    因此,相同的运算符优先级适用于预处理表达式、常量表达式和运行时求值。

    7.3.1 运算符优先级和关联性

    (...)

    7.11 逻辑与 &

    7.11 逻辑异或 ^

    7.11 逻辑或 |

    7.12 条件与 &&

    7.12 条件或 ||

    (...)

    从最高到最低优先级。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2011-10-25
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多