我想了解为什么DWORD值经常在MSDN上以hex描述。
我分析这个的原因是因为我试图从根本上理解为什么所有这些不同的数字数据types存在。 一位当地的导师暗示,DWORD和其他微软types的创build与处理器的发展有关。 这为我理解这些数据types提供了意义和上下文。 我想要更多的背景和背景。
无论哪种方式,我可以使用一些解释或一些资源如何记住DWORD,无符号整数,字节,位,WORD等之间的差异。
总之,我的问题是:1)为什么DWORD以hex表示? 2)您能否提供有关数值数据types之间差异的资源以及它们为何被创build?
计算机中的所有东西都是一堆0和1。 但是用二进制写一个完整的DWORD是相当单调乏味的:
00000000 11111111 00000000 11111111
为了节省空间并提高可读性,我们希望以较短的形式写出来。 十进制是我们最熟悉的,但不能很好地映射到二进制。 八进制和十六进制映射相当方便,与二进制位完全对齐:
// each octal digit is exactly 3 binary digits 01 010 100 binary = 124 octal // each hexadecimal digit is exactly 4 binary digits 0101 0100 binary = 54 hexadecimal
由于十六进制与8位字节(2个十六进制数字形成一个字节)很好地结合在一起,所以符号被卡住了,这就是最常用的。 阅读起来更容易,更容易理解,更容易排列位置。
标识正在使用哪个基地的正常简写:
1234543 = decimal 01234543 = octal (leading zero) 0x1234543 = hexadecimal (starts with 0x)
至于你有关BYTE,WORD,DWORD等的问题
电脑开始有点。 只有1或0.他在原来的Tron有一个客串。
字节是8位长(好的,曾经有7位字节,但我们可以忽略这些字节)。 这允许你有一个从0-255的数字,或从-128到127的有符号数字。比1/0好,但仍然有限。 您可能已经听说过“8位游戏”的提法。 这就是我们所说的。 该系统是围绕字节构建的。
然后,计算机发展到拥有16位寄存器。 这是2字节,并成为一个WORD(不,我不知道为什么)。 现在,数字可以是0-65535或-32768到32767。
我们继续需要更多的权力,电脑扩展到32位寄存器。 4字节,2个字,也被称为DWORD(双字)。 到目前为止,您可以查看“C:\ Windows”并查看“系统”(旧的16位碎片)和“system32”(新的32位碎片)的目录。
然后是QWORD(四字)。 4个字,8个字节,64位。 有没有听说过任天堂64? 这就是名字的来源。 现代建筑现在在这里。 CPU的内部包含64位寄存器。 您通常可以在此类cpus上运行32位或64位操作系统。
这包括位,字节,单词,双字。 这些都是原始类型,常用于标志,位掩码等。如果要保存实际的数字,最好使用有符号/无符号整数,长整型等。
我没有涉及浮点数,但希望这有助于总体思路。
DWORD常量通常以十六进制编写,当它们被用作可按位方式一起“或”运算的标志时。 这使得更容易看到这一点。 这就是为什么你看到0x01,0x02,0x04,0x08,0x10,0x20等等。程序员只是将这些值识别为具有二进制表示,只有一个位集。
当它是一个枚举,你会看到0x01,0x02,0x03等。他们往往仍然是十六进制编写的,因为程序员倾向于进入这些习惯!
为了记录,16位无符号数据被命名为WORD,因为当时计算机有16位寄存器。
在计算机历史上,8位数据可以存储在寄存器上的最大数据。 因为它可以存储ASCII字符,所以通常称为CHAR。
但16位电脑出来了,CHAR不适合命名16位数据。 所以16位数据通常被称为WORD,因为它是可以存储在一个寄存器中的最大数据单位,并且继续为CHAR创建一个数据是一个很好的比喻。
所以,在一些电脑上,使用不同的CPU WORD通常是指寄存器的大小。 在土星CPU上,使用64位寄存器,WORD是64位。
当32位x86处理器出来时,出于兼容性原因,WORD保持了16位,并且创建了DWORD以将其扩展到32位。 QWORD和64位也是如此。
至于为什么十六进制通常用来描述一个WORD,它必须对与它的注册来源有关的WORD的定义的性质做出定义。 在汇编程序编程中,您使用十六进制来描述数据,因为处理器只知道binray整数(0和1)。 而十六进制是一个更紧凑的方式来使用二进制,仍然保留它的一些属性。
为了详细说明Tim的答案,这是因为将Hex转换为二进制数字并返回非常容易 – 每个十六进制数字是4个二进制数字:
0x1 = 0001 0x2 = 0010 ... 0xD = 1101 0xE = 1110 0xF = 1111
所以, 0x2D
= 0010 1101
你有非常有趣和棘手的问题。
简而言之,有两个驱动因素导致了竞争类型家族的存在 – 基于DWORD的和基于int的:
1)一方面希望具有跨平台性,另一方面希望具有非常大的尺寸类型。
2)人民保守主义。
无论如何要提供详细的答案给你的问题和这个领域的足够好的背景,我们必须深入到电脑的历史。 从计算的早期开始我们的故事。
首先,机器词有这样的概念。 机器字是在特定的处理器中自然处理的二进制数据的一小部分。 所以,机器字的大小几乎不依赖于处理器,并且通常等于基本的内部处理器寄存器的大小。 通常它可以细分为两个相同的部分,也可以被处理器作为独立的数据块访问。 例如,在x86处理器上,机器字的大小是32位。 这意味着所有通用寄存器(eax,ebx,ecx,edx,esi,edi,ebp,esp和eip)具有相同的大小(32位)。 但是其中很多可以作为注册的一部分进行访问。 例如,您可以将32位数据块ax,16位数据块或8位数据块等作为eax访问。 但不是物理上这是一个32位寄存器。 我认为你可以在维基百科(http://en.wikipedia.org/wiki/Word_(computer_architecture))上的该领域找到很好的背景。 简而言之,机器字是多少位数据块可以用作单个指令的整数操作数。 即使在今天,不同的处理器架构也有不同的机器字大小
好的,我们对计算机字有一些了解。 现在是回到计算历史的时候了。 第一款受欢迎的英特尔x86处理器拥有16位字大小。 它于1978年上市。那时,如果不是主要的编程语言,汇编程序是非常受欢迎的。 正如你所知道的,汇编器在本机处理器语言下只是一个很薄的包装器。 由于这个,它依赖于硬件。 而当英特尔将他们新的8086处理器推向市场时,他们首先需要获得成功,也是把新处理器的组装器推向市场。 没有人想要一个没有人知道如何编程的处理器。 而且,当Intel为8086的汇编程序提供不同数据类型的名称时,由于8086的机器字具有16位大小,因此它们将明显的chois和名称16位数据块作为一个字。 机器字的一半称为字节(8位),两个字作为一个操作数称为双字(32位)。 Intel在处理器手册和汇编助记符(db,dw和dd用于字节,字和双字的静态分配)中使用了这些术语。
多年过去了,1985年,随着80386处理器的推出,英特尔从16位架构转向了32位架构。 但当时有很多开发者习惯于这个词是16位的价值。 除此之外,还有大量的软件是用真正的相信写的,这个字是16位的。 而且许多已经编写的代码依赖于字是16位的。 由于这个原因,除了机器字大小实际发生了变化之外,符号保持不变,除了新数据类型到达汇编器 – 四字(64位),因为依赖于两机的指令单词保持不变,但机器词扩展了。 同样的,双四字(128位)现在是用64位的AMD64架构来实现的。 因此,我们有
byte = 8 bit word = 16 bit dword = 32 bit qword = 64 bit dqword = 128 bit
请注意,该类型家庭主要的是它是强大的类型家庭。 因为它来自于汇编程序,所以需要使用大小不变的数据类型。 需要注意的是,多年以来,这个家族的数据类型仍然具有相同的常量,除此之外,其名称已经不具有其本来的意义。
另一方面,同时,高级语言也逐年普及。 而且因为这种语言是在跨平台应用的基础上发展起来的,从绝对的角度来看待内部数据类型的大小。 如果我正确地理解没有一个高级语言没有明确声明其内部的一些数据类型有一个固定的大小,将来不会改变。 我们来看看C ++的例子。 C ++标准版说明:
"The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set and is composed of a contiguous sequence of bits, the number of which is implementa- tion-defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order bit. The memory available to a C++ program consists of one or more sequences of contiguous bytes. Every byte has a unique address."
所以,我们可以看到令人惊讶的信息 – 在C ++中,甚至字节也没有任何不变的大小。 所以即使我们习惯于认为有8位的大小,根据C ++不但可以是8位,而且还可以是9,10,11,12等位。 甚至可能是7位。
"There are five signed integer types: “signed char”, “short int”, “int”, and “long int”., and “long long int”. In this list, each type provides at least as much storage as those preceding it in the list. Plain ints have the natural size suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs."
该引用描述了两个主要的主张:
1)sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)<= sizeof(long long)
2)plain int具有执行环境的体系结构所建议的自然大小。 这意味着int必须具有目标处理器体系结构的机器字大小。
你可以通过所有的C ++标准文本,但是你将无法找到像“大小为4字节”或“长度为64位”的东西。 特定整数C ++类型的大小可以随着从一个处理器架构移动到另一个处理器架构而改变,并且从一个编译器移动到另一个。 但是,即使你用c ++编写程序,你也会周期性地面对需要使用众所周知的常量大小的数据类型。
至少早期的编译器开发人员遵循这个标准声明 但是现在我们可以看到人们的保守主义又一次进入了这个剧本。 人们曾经认为int是32位,可以存储从-2,147,483,648到2,147,483,647的值。 早些时候,行业通过16位和32位架构之间的边界。 第二个要求是严格执行的。 当你使用C ++编译器来创建16位程序时,编译器使用16位处理器的16位大小的“int size”,而使用另一个C ++编译器来创建32位程序,但是,从相同的源代码,编译器使用int 32位大小是“自然大小”的32位处理器。 现在,例如,如果你看一下微软C ++编译器,你会发现它将使用32位整型,而不管目标处理器体系结构(32位还是64位),只是因为人们认为int是32位!
作为summury,我们可以看到,这是两个数据类型的家庭 – 基于dword和基于int的。 第二个动机是显而易见的 – 跨平台的应用程序开发。 第一层的动机是所有情况下,认为变量的大小是有意义的。 例如,除其他外,我们可以提到下一种情况:
1)在预知的范围内你需要有一些价值,你需要使用它的类或者在另一个数据结构中,这个数据结构将会在运行时间里被填充到大量的实例中。 在这种情况下,如果您将使用基于int的类型来存储该值,则会在某些体系结构中存在大量内存开销的缺陷,并有可能在另一个体系结构上破坏逻辑。 例如,您需要操作范围从0到1000000的值。如果要使用int来存储它,则如果int将为32位,则每个值实例将具有4字节的内存开销,如果int将是64位,并且如果int将是16位将不会正确工作。
2)涉及到网络的数据。 为了能够在不同的PC上正确处理您的网络协议,您需要以普通的基于大小的格式指定它,这将描述所有数据包和报头。 如果在一台PC上,你的网络通信将被完全破坏,你的协议头将是32位的长度为20个字节,在另一台PC上,它将是64个字节的长度为28个字节的长度。
3)您的程序需要存储用于某些特殊处理器指令的值,或者您的程序将与汇编器中编写的模块或代码块进行通信。
4)您需要用于与设备通信的商店值。 每个设备都有自己的特定描述,描述什么样的输入设备需要作为输入,以什么形式提供输出。 如果设备需要16位值作为输入,则无论int大小如何,即使安装了设备的系统上的处理器所使用的机器字大小,也必须接收相同的16位值。
5)你的算法依赖于整数溢出逻辑。 例如,你有2 ^ 16条目的数组,并且你想要有顺序地遍历它并刷新条目值。 如果你将使用16位整数,你的程序将会完美的工作,但是如果你移动到32位整数使用你将有超出范围的数组索引访问。
由于这个微软使用这两种数据类型。 在实际数据大小不重要的情况下,基于Int的类型,以及基于DWORD的情况。 即使在这种情况下,Microsoft也将这两个宏定义为宏,以便快速且容易地将Microsoft使用的虚拟类型系统分配给特定的处理器体系结构和/或编译器,并将其分配给正确的C ++等价物。
我希望我已经很好地回答了数据类型的起源和差异的问题。
所以,我们可以切换到seqond问题为什么使用十六进制数字来表示基于DWORD的数据类型值。 实际上有几个原因:
1)如果我们使用stricktly大小的二进制数据类型,那么我们可以期望以二进制形式查看它们。
2)当以二进制形式编码时,很容易理解位掩码值。 同意,如果在下一个表单中有值,那么就可以更容易地设置哪个位被设置,以及哪个位被重置
1100010001011001
那么如果它将被编码在下一个形式
50265
3)以二进制形式编码的数据和描述一个基于DWORD的值具有恒定的长度,当以十进制形式编码的相同数据将具有可变长度时。 请注意,即使小数字以二进制形式编码,也提供完整的值描述
0x00000100
代替
0x100
二进制编码的这种性质在需要分析大量二进制数据的情况下是非常有吸引力的。 例如,十六进制编辑器或分析您的程序在调试器中使用的普通内存,当您的断点被击中。 同意,在整齐排列的可变大小的值的整齐列上看看要舒服得多。
所以,我们决定我们要使用二进制编码。 我们有三个选择:使用普通的二进制编码,使用八进制编码和使用十六进制编码。 Peple prefere使用十六进制编码,因为它是可用编码集合中最短的。 只是比较
10010001101000101011001111000
和
0x1234568
你能很快找到在下一个值中设置的位数吗?
00000000100000000000000000000
然后呢?
0x00100000
在第二种情况下,您可以快速将数字分成四个分隔字节
0x00 0x10 0x00 0x00 3 2 1 0
在每一个中,第一个数字表示4个最高有效位,而第二个数字表示另外4个最低有效位。 在花了一些时间处理十六进制值之后,您将会记住每个十六进制数字的简单位模拟,并且会在头脑中相互替换,而不会有任何问题:
0 - 0000 4 - 0100 8 - 1000 C - 1100 1 - 0001 5 - 0101 9 - 1001 D - 1101 2 - 0010 6 - 0110 A - 1010 E - 1110 3 - 0011 7 - 0111 B - 1011 F - 1111
所以,我们只需要一到两个就可以发现我们已经设置了位数20!
人们使用十六进制,因为它是最短的,舒适的undestand和使用二进制数据编码的形式。