Понимание Endianness - значение переменной - PullRequest
3 голосов
/ 05 января 2012

Я использую фрагмент кода (который можно найти на этом сайте), который проверяет порядок байтов во время выполнения.

static bool isLittleEndian()
{
  short int number = 0x1;
  char *numPtr = (char*)&number;

  std::cout << numPtr << std::endl;
  std::cout << *numPtr << std::endl;

  return (numPtr[0] == 1);
}

В режиме отладки значение numPtr выглядит так: 0x7fffffffe6ee "\001"

Я предполагаю, что первая шестнадцатеричная часть является адресом памяти указателя, а вторая часть является значением, которое он содержит.Я знаю, что \ 0 - это нулевое завершение в старом стиле C ++, но почему оно находится впереди?Это связано с порядком байтов?
На машине с прямым порядком байтов: 01 первый байт и, следовательно, наименее значимый (позиция байта 0) и \ 0 второй / последний байт (позиция байта 1)?

Кроме того, операторы cout не печатают адрес указателя или его значение.Причины для этого?

Ответы [ 7 ]

2 голосов
/ 05 января 2012

Другие дали вам четкий ответ на то, что означает "\000", так что это ответ на ваш вопрос:

На машине с прямым порядком байтов: 01 первый байт и, следовательно, наименьшийзначащий (байтовый разряд 0) и \ 0 второй байт / последний байт (байтовый разряд 1)?

Да, это правильно.Вы смотрите на значение как 0x1234, оно состоит из двух байтов, старшей части 0x12 и младшей части 0x34.Термин «младший порядок» означает, что младшая часть сначала сохраняется в памяти:

addr:   0x34
addr+1: 0x12

Знаете ли вы, что термин «порядковый номер» предшествовал компьютерной индустрии?Первоначально он был использован Джонатаном Свифтом в его книге Путешествия Гулливера , где описывалось, едят ли люди яйцо из заостренного или круглого конца.

1 голос
/ 05 января 2012

Для начинающих: этот тип функции абсолютно бесполезен: на машине, где sizeof(int) равно 4, существует 24 возможных порядка байтов.Большинство, конечно, не имеет смысла, но я видел по крайней мере три.И порядковый номер не единственное, что влияет на целочисленное представление.Если у вас есть int, и вы хотите получить младшие 8 бит, используйте intValue & 0xFF, для следующих 8 бит, (intValue >> 8) & 0xFF.

Что касается вашего точного вопроса: я предполагаю, чтовы описываете как «похоже на это» то, что вы видите в отладчике, когда вы ломаетесь при возврате.В этом случае numPtr является char* (unsigned char const* имело бы больше смысла), поэтому отладчик принимает строку в стиле C.0x7fffffffe6ee является адресом;то, что следует, - это то, что компилятор видит как строку стиля C, которую он отображает как строку, то есть "...".Предположительно, ваша платформа является традиционным прямым порядком байтов (Intel);указатель на строку стиля C видит последовательность (числовые значения) 1, 0.0 является, конечно, эквивалентом '\0', поэтому он считает, что это строка из одного символа, причем этот один символ имеет кодировку 1. Не существует печатного символа с кодировкой, равной единице, и он не соответствуетк любой из нормальных escape-последовательностей (например, '\n', '\t' и т. д.).Таким образом, отладчик выводит его, используя восьмеричную escape-последовательность, '\', за которой следуют от 1 до 3 восьмеричных цифр.(Традиционный '\0' является лишь частным случаем этого; '\', за которым следует одна восьмеричная цифра.) И он выводит 3 цифры, потому что (вероятно) он не хочет смотреть в будущее, чтобы гарантировать, что следующий символне восьмеричная цифра.(Если бы последовательность состояла из двух байтов 1, 49, например, 49 равняется '1' в обычных кодировках, и если он выдает только один байт для восьмеричного кодирования 1, результатом будет "\ 11", чтоэто строка из одного символа, соответствующая в обычных кодировках '\t'.) Таким образом, вы получите " это строка, \001 с первым символом, имеющим кодировку 1 (и не отображаемое представление), и "это конец строки.

1 голос
/ 05 января 2012

Это не \0, за которым следует "01", это один символ \001, который представляет число 1 в восьмеричном. Это единственный байт "в" вашей строке. После него есть еще один байт со значением ноль, но вы этого не видите, поскольку он рассматривается как терминатор строки.

1 голос
/ 05 января 2012

Самый простой способ проверить порядок байтов - позволить системе сделать это за вас:

if (htonl(0xFFFF0000)==0xFFFF0000) printf("Big endian");
else printf("Little endian");
0 голосов
/ 05 января 2012

Кроме того, операторы cout не печатают адрес указателя или это ценность. Причины для этого?

Поскольку символы и указатели на символы обрабатываются иначе, чем целые, когда дело доходит до печати. ​​

Когда вы печатаете символ, он печатает символ из того набора символов, который используется. Обычно это ASCII или некоторый расширенный набор ASCII. Значение 0x1 в ASCII не печатается.

Когда вы печатаете указатель на символ, он не печатает адрес, он печатает его как строку с нулевым символом в конце.

Чтобы получить желаемые результаты, приведите указатель на символ к пустому указателю и приведите его к типу int.

std::cout << (void*)numPtr << std::endl;
std::cout << (int)*numPtr << std::endl;
0 голосов
/ 05 января 2012

\ 0 не является NUL, отладчик показывает вам numPtr в виде строки, первым символом которой является \ 001 или control-A в ASCII.Второй символ \ 000, который не отображается, потому что NUL не отображаются при отображении строк.Двухзначная строковая версия 'number' будет отображаться как "\ 000 \ 001" на машине с прямым порядком байтов, а не "\ 001 \ 000", как на машинах с прямым порядком байтов.

0 голосов
/ 05 января 2012

"\001" вы видите только один байт. Вероятно, это восьмеричная запись, для которой нужно три цифры, чтобы правильно выразить (десятичные) значения от 0 до 255.

...