Почему значения DWORD обычно представлены в шестнадцатеричном формате?

Я пытаюсь понять, почему значение DWORD часто описывается в шестнадцатеричном формате на MSDN.

причина, по которой я анализирую это, заключается в том, что я пытаюсь понять фундаментально, почему существуют все эти различные типы данных чисел. Местный наставник намекнул мне, что создание DWORD и других типов Microsoft имеет какое-то отношение к эволюции процессоров. Это придает смысл и контекст моему пониманию этих типов данных. Я хотел бы больше контекста и фон.

в любом случае, я мог бы использовать некоторые объяснения или некоторые ресурсы о том, как запомнить разницу между DWORD, целыми числами без знака, байтами, битами, словом и т. д.

вкратце, мои вопросы: 1) Почему DWORDs представлены в Hex? 2) Можете ли вы выделять различия между числовыми типами данных, и почему они были созданы?

5 ответов


все в компьютере-это куча нулей и единиц. Но писать целый DWORD в двоичном формате довольно утомительно:

00000000 11111111 00000000 11111111

чтобы сэкономить место и улучшить читаемость, мы хотели бы написать его в более короткой форме. Decimal-это то, с чем мы наиболее знакомы, но не сопоставляем хорошо с двоичным. Восьмеричная и шестнадцатеричная карта довольно удобно, выстраиваясь точно с двоичными битами:

// 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. У него была камея в оригинальном троне.

байты имеют длину 8 бит (ну, когда-то были 7-битные байты, но мы можно игнорировать те). Это позволяет иметь число от 0-255 или подписанное число от -128 до 127. Лучше, чем просто 1/0, но все же ограничен. Возможно, вы слышали ссылки на"8-битные игры". Вот что мы имеем в виду. Система была построена на байтах.

затем компьютеры выросли до 16-битных регистров. Это 2 байта и стало известно как слово (Нет, я не знаю, почему). Теперь числа могут быть от 0-65535 или от -32768 до 32767.

мы продолжали хотеть больше силы, и компьютеры были расширены до 32-разрядных регистров. 4 байта, 2 слова, также известный как DWORD (двойное слово). И по сей день ты можешь заглядывать". C:\Windows "и см. каталог для" системы "(старые 16-битные части) и" system32 " (новые 32-битные компоненты).

затем появилось QWORD (quad-word). 4 слова, 8 байт, 64 бита. Когда-нибудь слышали о Nintendo-64? Вот откуда взялось это имя. Современная архитектура теперь здесь. Внутренние части процессора содержат 64-разрядные регистры. Обычно вы можете запустить 32-или 64-разрядная операционная система на таких процессорах.

это охватывает бит, байт, слово, Dword. Это необработанные типы и часто используются для флагов, битовых масок и т. д. Если вы хотите сохранить фактическое число, лучше всего использовать целое число со знаком / без знака, длинное и т. д.

Я не покрывал числа с плавающей запятой, но, надеюсь, это поможет с общей идеей.


константы DWORD обычно записываются в hex, когда они используются в качестве флагов, которые могут быть или вместе побитовым способом. Это облегчает понимание того, что это так. Вот почему вы видите 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 и т. д. Программисты просто распознают эти значения как двоичные представления с одним битовым набором.

когда это перечисление, вы увидите 0x01, 0x02,0x03 и т. д. Они часто все еще написаны на hex, потому что программисты склонны к этим привычкам!


только для записи 16-битные неподписанные данные называются WORD beacause в то время, компьютеры имели 16-битные регистры.

в истории компьютера, 8 бит данных, где самые большие данные можно хранить в реестре. Поскольку он мог хранить символ ascii, его обычно называли CHAR.

но 16-битный компьютер вышел, и CHAR не соответствовал названию 16-битных данных. Таким образом, 16-битные данные обычно назывались словом, потому что это была самая большая единица данных, которую вы могли хранить на одном регистре, и это была хорошая аналогия, чтобы продолжить тот, который был сделан для CHAR.

Итак, на некоторых компьютерах использование другого слова CPU обычно относится к размеру регистра. На Saturn CPU, который использует 64-битный регистр, слово составляет 64 бита.

когда 32-битные процессоры x86 вышли, WORD остался 16 бит по соображениям совместимости, и DWORD был создан, чтобы расширить его до 32 бит. То же самое верно для qword и 64 бит.

А почему шестнадцатеричное широко используется чтобы описать слово, оно должно иметь отношение к природе определения слова, которое привязано к его регистровому происхождению. В ассемблерном программировании вы используете шестнадцатеричное для описания данных, потому что процессоры знают только binray intergers (0 и 1). И шестнадцатеричный-это более компактный способ использования двоичного кода и сохранения некоторых его свойств.


чтобы уточнить ответ Тима, это потому, что преобразование Hex в двоичный и обратно очень легко - каждая шестнадцатеричная цифра составляет 4 двоичных цифры:

0x1 = 0001
0x2 = 0010
...
0xD = 1101
0xE = 1110
0xF = 1111

и 0x2D = 0010 1101


у Вас очень интересный и каверзный вопрос.

короче говоря, было два драйвера, которые приводят к существованию семейств конкурирующих типов-DWORD-based и int-based:

1) Желание иметь crosspltformity с одной стороны и stricktly типы размера с другой стороны.

2) консерватизм народов.

в любом случае для того чтобы обеспечить полный детальный ответ к вам вопрос и хорошая предпосылка этого поля мы должны выкопать в компьютерная история. И начнем нашу историю с первых дней вычислительной техники.

хорошо, у нас есть некоторое понимание компьютерного слова. Настало время вернуться в историю вычислительной техники. Первые популярные процессоры Intel x86 имели 16-битный размер слова. Он пришел на рынок в 1978. В то время ассемблер был очень популярен, если не основной язык программирования. Как вы знаете, ассемблер-это просто очень тонкая оболочка под родной язык процессора. Из-за этого он зависит от оборудования enterely. И когда Intel выталкивает новый процессор 8086 на рынок, Первое, что им нужно было для достижения успеха, - это также выталкивать ассемплер для нового процессора на рынок. Никому не нужен процессор, который никто не умеет программировать. И когда Intel дала имена для различных типов данных в ассемблере для 8086 они делают очевидный выбор и называют 16-битный фрагмент данных как слово, потому что машинное слово 8086 имеет 16-битный размер. Половина машинного слова называлась byte (8-bit), а два слова, используемые в качестве одного операнда, назывались double word (32-bit). Intel использовала эти термины в руководствах по процессорам и в ассемблерной мнемонике (db, dw nd dd для статического выделения байта, слова и двойного слова).

прошли годы и 1985 Intel перешла от 16-разрядной архитектуры к 32-разрядной с внедрением процессора 80386. Но в то время было огромное количество разработчиков, которые привыкли к тому, что слово имеет 16-битное значение. Кроме того, было огромное количество мягкого было написано с истинным убеждением, что слово 16-битное. И многие из уже написанного кода полагаются на то, что слово 16 бит. Благодаря этому, помимо того, что размер машинного слова фактически был изменен, нотация осталась прежней, за исключением того, что этот новый тип данных прибыл в слово ассемблера-quad (64-бит), потому что инструкция, которая полагается на два машинных слова, осталась прежней, но машинное слово было расширено. Точно так же слово double quad (128-бит) появилось теперь с 64-битной архитектурой AMD64. В результате мы имеем

byte    =   8 bit
word    =  16 bit
dword   =  32 bit
qword   =  64 bit
dqword  = 128 bit

обратите внимание, что главное в этом семействе типов заключается в том, что оно имеет большой размер. Поскольку он исходит из и широко используется в ассемблере, для этого требуются типы данных с константой размер. Обратите внимание, что годы проходят по одному, но типы данных из этого семейства продолжают иметь одинаковый постоянный размер, помимо того, что его имя уже не имеет своего первоначального значения.

С другой стороны, в то же время с каждым годом языки высокого уровня становились все более популярными. И потому, что languges был разработан с кросс-платформенным приложением в уме thay посмотрел на размеры своих внутренних типов данных с совершенно другой точки зрения. Если я правильно понимаю ни один язык высокого уровня четко не утверждает, что некоторые из его внутренних типов данных имеют фиксированный постоянный размер, который никогда не будет изменен в будущем. Давайте не смотреть на 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)

2) простые Инты имеют естественный размер, предложенный архитектурой среды выполнения. Это означает, что int должен иметь размер машинного слова архитектуры целевого процессора.

вы можете пройти через весь стандартный текст C++, но вы не сможете найти что-то вроде " размер int равен 4 байт" или "длина 64 бит". Размер отдельных целочисленных типов C++ может изменяться при переходе от одной архитектуры процессора к другой и при переходе от одного компилятора к другому. Но даже когда вы пишете программу на c++, вы периодически сталкиваетесь с необходимостью использовать типы данных с известным постоянным размером.

по крайней мере, более ранние разработчики компиляторов следовали этим стандартным утверждениям. Но теперь мы видим, что консерватизм людей входит в игру еще раз. Люди раньше считалось, что int 32-разрядный и может хранить значения из диапазона от -2,147,483,648 до 2,147,483,647. Раньше, когда промышленность проходила границу между 16-битной и 32-битной архитектурой. Второе требование было строго исполнено. И когда вы использовали C++ компилятор для создания 16-разрядных программ, компилятор использовать тип int 16-битный размер, ЧТО ТАКОЕ "натуральный размер" для 16-разрядных процессоров и, напротив, когда ты использовал другой компилятор C++ для создания 32-разрядных программ, но из того же исходного кода, компилятор использовать тип int с 32-битной размер "натурального размера" для 32-разрядных процессоров. В настоящее время, если вы посмотрите, например, на компилятор Microsoft c++, вы обнаружите, что он будет использовать 32-разрядный int независимо от архитектуры целевого процессора (32-разрядный или 64-разрядный) только потому, что люди привыкли думать, что int 32-разрядный!

как summury, мы можем видеть, что thare - это два семейства типов данных - на основе dword и int. Мотивация для второго очевидна-кросс-платформенная разработка приложений. Мотивация для fisrt - это все случаи, когда учет размеров переменных имеет смысл. Например, среди прочих можно упомянуть следующие случаи:

1) вам нужно иметь некоторое значение в предопределенном хорошо известном диапазоне, и вам нужно использовать его класс или в другой структуре данных, которая будет заполняться огромным количеством экземпляров во время выполнения. В этом случае, если вы будете использовать типы на основе int для хранения этого значения, это будет иметь недостаток в огромных накладных расходах памяти на некоторых архитектурах и потенциально может сломать логику на другом. Например вам нужно манипулировать значениями в диапазоне от 0 до 1000000. Если вы используете int для ее хранения, то программа будет правильно себя вести, если int будет 32-битный, будет 4 байта памяти для каждого значения если int будет 64-битным, и он не будет работать правильно, если инт будет 16-битным.

2) Данные, участвующие в nextworking. Чтобы иметь возможность правильно обрабатывать сетевой протокол на разных ПК, вам понадобится чтобы указать его в простом формате на основе размера, который будет описывать все пакеты и заголовок бит за битом. Ваша сетевая связь будет полностью нарушена, если на одном ПК заголовок протокола будет иметь длину 20 байт с 32-битным, а на другом ПК-длину 28 байт с 64-битным int.

3) Ваша программа должна хранить значение, используемое для некоторых специальных инструкций процессора, или ваша программа будет взаимодействовать с модулями или фрагментами кода, написанными в ассемблере.

4) Вам нужно хранить значения, которые будут использоваться для связи с устройствами. Каждое устройство имеет свою спецификацию, которая описывает, какое устройство ввода требуется в качестве входа и в какой форме оно будет обеспечивать выход. Если устройству требуется 16-разрядное значение в качестве входного, оно должно получить равное 16-разрядное значение независимо от размера int и даже независимо от размера машинного слова, используемого процессором в системе, где установлено устройство.

5) Ваш алгоритм полагается на логику переполнения целого числа. Например, у вас есть массив из 2^16 записей, и вы хотите infenitely и sequentely идет через него, и значения записей обновления. Если вы будете использовать 16-битный int, ваша программа будет работать отлично, но wimmediatelly вы переходите к 32-битному использованию int, у вас будет доступ к индексу массива вне диапазона.

из-за этого Microsoft использует оба семейства типов данных. Типы на основе Int в случае, когда фактический размер данных не имеет большого значения, и DWORD-в случаях, когда он имеет. И даже в этом случае Microsoft определить как макросы, чтобы обеспечить возможность быстро и достаточно легко принять систему виртуального типа, используемую Microsoft для конкретной архитектуры процессора и/или компилятора, назначив ему правильный эквивалент c++.

Я надеюсь, что я достаточно хорошо рассмотрел вопрос о происхождении типов данных и их различиях.

Итак, мы можем перейти к вопросу seqond о том, почему шестнадцатеричная цифра используется для обозначения значений типов данных на основе DWORD. На самом деле их немного причины:

1) Если мы используем двоичные типы данных stricktly-sized, это будет достаточно очевидно, что мы можем захотеть посмотреть на них в двоичной форме.

2) очень легко понять значения битовых масок, когда они закодированы в двоичной форме. Согласитесь, что гораздо проще понять, какой бит установлен и какой бит сбрасывается, если значение в следующей форме

1100010001011001

тогда, если он будет закодирован в следующей форме

50265

3) данные, закодированные в двоичной форме и описанное одно значение на основе DWORD имеет постоянную длину, когда те же данные, закодированные в десятичной форме, будут иметь переменную длину. Обратите внимание, что даже если небольшое число кодируется в двоичной форме, полное описание значение

0x00000100

вместо

0x100

это свойство двоичного кодирования очень привлекательно в том случае, когда требуется анализ огромного количества двоичных данных. Например, редактор hex или анализ простой памяти используется программой в отладчике при попадании в точку останова. Согласитесь, что гораздо удобнее смотреть на аккуратные столбцы значений, которые к куче слабо выровненных значений размера переменной.

Итак, мы решили, что хотим использовать двоичное кодирование. У нас есть три варианта: использовать обычное двоичное кодирование, восьмеричное кодирование и шестнадцатеричное кодирование. Peple предпочитает использовать шестнадцатеричное кодирование, потому что оно наиболее короткое из набора доступных кодировок. Просто сравнить

10010001101000101011001111000

и

0x1234568

можете ли вы быстро найти числа битов, которые установлены в следующем значении?

00000000100000000000000000000

и в следующем?

0x00100000

во втором случае вы можете быстро разделить число на четыре разделенных байта

0x00 0x10 0x00 0x00
   3    2    1    0

в каждом из которых первая цифра обозначает 4 наиболее значимых бита, а вторая - еще 4 наименее значимых бита. После того, как вы потратите некоторое время на работу с hex значения вы запомните простой битовый аналог каждой шестнадцатеричной цифры и без проблем замените одно на другое в уме:

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!

люди используют hex, потому что он самый короткий, удобный для undestand и использовать форму двоичного кодирования данных.