.NET中的GUID字节顺序

22

我正在创建一个类似于这样的 GUID:

Guid g = new Guid(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF });
Console.WriteLine(g);

这将输出

03020100-0504-0706-0809-0a0b0c0d0e0f

根据维基百科(Wikipedia)的说法,guid有四个部分,这也解释了为什么字节顺序要在四组之间切换。然而,维基百科文章还指出,所有部分都以Big Endian格式存储。显然,前三个部分不是Big Endian。Guid的GetBytes()方法返回的字节与创建时使用的完全相同的顺序。这种行为的解释是什么?

2个回答

11

看起来微软将这五个部分存储在一个结构体中。 前四个部分的长度为2或4字节,因此可能以本机类型(即WORD和DWORD)的形式以小端格式存储。由于最后一个部分长度为6字节,因此处理方式不同(可能是一个数组)。

规范是否说明GUID按大端序存储,还是部分按该顺序存储但各个部分可能具有实现特定性?

编辑:

根据UUID规范第4.1.2节“布局和字节顺序”(强调我的):

为了尽量避免对一个八位组内位赋值的混淆,UUID记录定义仅以八位组的积分数字段为基础定义。这些字段按最重要的位首先呈现。

...

在没有明确的应用程序或显示协议规范相反的情况下,UUID被编码为128位对象,如下所示:

使用上述定义的大小和顺序,将字段编码为16个八位组,并使每个字段的最重要字节(也称为网络字节顺序)首先编码。

可能微软已经按正确的顺序存储了这些字节,但为了呈现而没有将WORD和DWORD部分转换为主机序(至少在我粗略阅读规范时似乎没问题)。


根据维基百科(我没有查阅参考资料),UUID标准,其中GUID应该是实现状态,规定部分应以大端编码。 UUID和GUID规范都定义了四个部分,按照4、2、2和8字节的大小顺序排列。 - Stilgar
确实,当显示最后8个字节时,通常会显示为2字节-6字节 - 这两个部分似乎都是正确的大端序(如您的示例所示)。 - Grhm
是的,最后8个字节在字符串表示中显示为2-6,可能是为了可读性,但它们是相同数据部分的一部分。真正的问题是Guid是否违反了标准,还是有其他解释。 - Stilgar
不错的发现。我在想我们现在是否应该更新维基百科的文章。 - Stilgar
在https://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way-it-does/77080208#77080208中,我提到了一个扩展方法`byte[] ToByteArrayMatchingStringRepresentation(Guid)`,我用它来修复这个差异,考虑到机器的字节顺序。 - undefined

8

虽然我在这方面不是专家,但你提到的维基页面也说:

然而,数据类型的一个常见结构的参考文献并没有提到字节顺序。

该引用([4])指向http://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx,该链接随后说明了Microsoft如何实现GUID:

typedef struct _GUID {
  DWORD Data1;
  WORD  Data2;
  WORD  Data3;
  BYTE  Data4[8];
} GUID;

由于最后8个字节被存储为一个字节数组,我认为这就是你所看到的行为的标识。


所以DWORD和WORD之所以是小端字节序,是因为某种原因吗? - Stilgar
1
这取决于你的架构。在x86架构上,是的。 - pms1969
1
但这也意味着GUID违反了UUID标准?同时维基百科的文章有点误导(声称GUID以大端格式存储数据部分)。 - Stilgar
1
@Stilgar:UUID标准和GUID文章仅说明它们以大端格式存储 - 似乎都没有明确说明GUID / UUID如何以人类可读的格式呈现。 - Grhm
1
大端序 = 人类可读。人类按照最重要的数字先写(至少在所有从左到右的书写系统中如此)。https://lwn.net/Articles/628233/ - MarcH

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