【问题标题】:Semantics of bool fields in explicit layout types (ECMA-334)显式布局类型中布尔字段的语义 (ECMA-334)
【发布时间】:2012-07-01 07:30:11
【问题描述】:

我正在尝试查找在 ECMA-334(C# 语言规范)中定义以下行为的位置。源程序如下。

static void Main(string[] args)
{
    TestStruct a = new TestStruct();
    a.byteValue = 1;
    TestStruct b = new TestStruct();
    b.byteValue = 2;

    Console.WriteLine(string.Format("Result of {0}=={1} is {2}.",
        a.boolValue, b.boolValue, a.boolValue == b.boolValue));
    Console.WriteLine(string.Format("Result of {0}!={1} is {2}.",
        a.boolValue, b.boolValue, a.boolValue != b.boolValue));
    Console.WriteLine(string.Format("Result of {0}^{1} is {2}.",
        a.boolValue, b.boolValue, a.boolValue ^ b.boolValue));
}

[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct TestStruct
{
    [FieldOffset(0)]
    public bool boolValue;
    [FieldOffset(0)]
    public byte byteValue;
}

执行结果如下。

Result of True==True is False.
Result of True!=True is True.
Result of True^True is True.

这违反了 §14.9.4 和 §14.10.3 两个部分,所以我假设其他地方有一个例外情况,涵盖这些情况。请注意,这不会影响使用 AND、OR、NAND 或 NOR 运算的代码,但会影响使用 XOR 和/或逻辑双条件运算的代码。

【问题讨论】:

  • 我的猜测是,虽然这两个字段的位值“足够真实”以至于 ToString() 会认为它们“真实”,但实际的 == 和 != 比较是按位进行的(因为它们是不应该以这种方式破坏的值类型),因此比较是不稳定的。你为什么做这个? :)

标签: c# boolean specifications language-specifications


【解决方案1】:

我怀疑这根本没有指定。当您明确布局结构时,您很可能会进入特定于架构和特定于实现的行为。

我强烈怀疑您所看到的行为都可以通过想象所有bool 操作都有效地转换为整数操作来解释,然后(在必要时)通过检查结果是否为非零来转换结果。通常这很好,只要所有 bool 值在内存中使用相同的值(1 或 0),但在你的情况下,你给它一个意外的值(2)。因此,尽管a.boolValueb.boolValue 都为真,a.boolValue ^ b.boolValue 具有对所涉及的两个字节进行异或运算的效果,得到 3,在必要时仍会转换为 true

最好避免使用这种代码,IMO。您是真的需要它,还是只是好奇?

【讨论】:

  • 语言规范明确指出(两次)运算符!=^bool 类型的操作数产生相同的结果。除非规范中提供了此规则的例外情况,否则 C# 编译器的当前实现正在引入特定于实现的行为,其中规范声明了明确的语义。请注意,这不涉及不安全的代码,因此架构和实现不应影响行为。
  • @280Z28:如果您设置了intfloat 的值,则将float 设置为(比如说)5.0 并打印出int 值,这将是架构/实现-具体的,不是吗?为什么你认为这是不同的?我认为当你故意像这样弄乱内存时,出现未定义的行为是合理的。
  • @280Z28 这几乎肯定不是 C# 编译器的错。 CLR 本身处理这些操作,并且可能为了提高效率,假设您没有故意破坏操作数。做任何其他事情(无论是在编译器还是 CLR 级别)都会完全浪费每个人的时间。
  • @dlev C# 在 ECMA-334 中指定。与包含__arglist 或其他特定于实现的关键字的程序相反,上面的程序是一个符合标准的程序(在第 3 页上定义)。不允许 C# 的一致实现偏离该程序的严格一致实现。在更改 C# 编译器或在 ECMA-334 附录 B(特别是 B.2、B.3 或 B.4)中解决这种情况之前,Microsoft C# 编译器不是标准化 C# 语言的符合要求的实现。跨度>
  • @280Z28:如果这会让您感到困扰,我可以提出任何数量的其他不严格符合的位,例如其中 CLR 允许 C# 语言不允许的引用转换...
猜你喜欢
  • 2015-03-13
  • 2019-04-03
  • 2015-09-27
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多