【问题标题】:IsLittleEndian field reports false, but it must be Little-Endian?IsLittleEndian 字段报错,但一定是 Little-Endian?
【发布时间】:2011-01-02 16:18:55
【问题描述】:

我在 Intel 计算机(Win7 64 位)上运行,根据我阅读的内容,Intel 正在使用 Little-Endian。我在 C# 中使用以下代码进行了尝试:

byte[] b2 = new byte[] { 0, 1 };
short b2short = BitConverter.ToInt16(b2, 0);

和 b2short == 256 正如 Little-Endian 所期望的那样。

然后我在 .NET 中读到,BitConverter.IsLittleEndian 应该反映系统使用的字节序,当我在 Visual Studio 中检查变量时,它会报告 false,即它不是 Little-字节序。

这与 64 位操作系统有关吗?有什么想法吗?


编辑: 坐在我对面的同事做了同样的测试(Win Vista 32 位)并得到了同样的结果


编辑 2: 这真的很奇怪。每当我运行代码并在 BitConverter 完成操作后中断时,IsLittleEndian == false。 但是,如果我添加行 Console.WriteLine(BitConverter.IsLittleEndian); 之后它是 TRUE:

byte[] b2 = new byte[] { 0, 1 };
short b2short = BitConverter.ToInt16(b2, 0);
Console.WriteLine(BitConverter.IsLittleEndian);
// Now the IsLittleEndian is true

但是一旦我删除 Console.WriteLine 它又是 false

我还可以补充一点,即使我在“Console.WriteLine”上中断 IsLittleEndian == true,但如果我完全删除该行,它就是 false。


编辑 3: 正如 Mark Gravell 指出的那样,这一定是一些时间错误。如果我使用变量 BitConverter.IsLittleEndian 它被初始化,如果我不(并且在中断时查看它)它没有被初始化,因此 false...

【问题讨论】:

  • 它是哪个英特尔?会不会是IA64?尽管我确信即使在 IA64 上它也可能使用 LE。
  • 重新使用 Console.WriteLine - 请参阅我关于“beforefieldinit”的观点...
  • 我使用的是 Intel i920 处理器...

标签: c# windows-7


【解决方案1】:

我想知道这是否是一个计时错误,可能与“beforefieldinit”有关......你如何看待这个价值?类型初始化程序(对于BitConverter)可能没有被 VS 调试器触发(可以这么说,它在幕后偷看)。特别是因为false 是字段的默认值...

IsLittleEndian 静态字段在静态构造函数中设置;初始化器执行的时间......很难预测。如果您使用的是调试器,那么所有的赌注都是关闭的。可靠地检查该字段的值的唯一方法是通过代码(当 CLR 将在需要它之前的某个时间点运行初始化程序时):

bool isLittleEndian = BitConverter.IsLittleEndian;

不要相信调试器/监视窗口等。

【讨论】:

  • 我正在通过破坏代码或 Console.Writeline 来查看它。可能是这样,它在破坏代码时没有初始化,但是当我在代码中使用它时它被初始化了,比如 Console.WriteLine。
  • 由于他说如果他完全删除该行是错误的,这使我认为他之前已经在该行上放置了断点,这将触发 before BitConverter is用过的。我想知道如果他在调用 ToInt16 之后添加了另一行,这与 BitConverter 没有任何关系,而是在该行上中断,会发生什么情况?
  • Lasse:如果使用 BitConverter.IsLittleEndian(如 Console.WriteLine),它甚至在行执行之前就已初始化。甚至在使用 BitConverter 之前也是如此。
  • 为了额外的乐趣:我刚刚发现这个只读属性实际上是通过视觉工作室“即时窗口”读/写的。您设置的值会在即时窗口和工具提示等中报告,但如果您访问代码中的标志,则不会。当您实际进行转换时,您设置的值也会被忽略。
  • 谢谢。我在想 WTF!
【解决方案2】:

Raymond Chen 对问题here 给出了扩展答案(镜像,格式更好here)。

它的要点是:

从调试器读取成员不会执行初始化该成员的代码。

所以当你在 Visual Studio 中查看该字段时,它会报告 false,因为静态初始化程序尚未运行。但是,如果您在代码中使用该字段,静态初始化程序运行,导致该字段返回实际正确的值。

【讨论】:

    【解决方案3】:

    你是怎么检查的?

    例如,运行这个简短的控制台应用程序:

    using System;
    
    public class Test
    {
        static void Main()
        {
            Console.WriteLine(BitConverter.IsLittleEndian);
        }
    }
    

    打印的是什么?您能否详细说明您正在使用的硬件和操作系统?

    【讨论】:

    • “它是一个属性而不是一个变量”——实际上,它是一个静态字段。
    • @Marc:是的,我刚刚删除了那个位,单独发现了它。真丢脸。
    • 乔恩:请阅读我上面的“编辑 2”作为您问题的答案。行为很奇怪……
    【解决方案4】:

    就像 Marc 所说的,这似乎是一个计时错误。使用 VS 调试器在启动时“窥视”该值会返回 false,但如果我在消息框中打印它会返回 true。

    【讨论】:

      猜你喜欢
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-01
      • 2011-10-06
      • 2012-10-09
      • 2019-06-30
      • 2010-10-16
      相关资源
      最近更新 更多