2010-02-11 3 views
8

Допустим, у меня есть целое число 4Byte, и я хочу, чтобы он передал его в короткое целое число 2Byte. Правильно ли, что в обоих (маленьком и большом конце) короткое целое будет состоять из 2 наименее значимых байтов этого целого числа 4Byte?Маленький endian Vs Большой endian

Второй вопрос:
Каков будет результат такого кода в процессорах с маленькими размерами и большим эндиантом?

int i = some_number; 
short s = *(short*)&i; 

ИМХО в большой процессор младшему 2 наиболее значимых байт будет скопирован, и в небольшой Endian будет скопировано 2 значащих байт.

+0

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

ответ

12

Я прав, что в обоих коротких целых будет состоять из 2 наименее значимых байтов этого 4-байтового целого числа?

Да, по определению.

Разница между bigE и littleE заключается в том, является ли младший старший байт на самом нижнем адресе или нет. На процессоре с маленьким номером наименьшие адреса являются наименее значимыми битами, x86 делает это таким образом.

Они дают тот же результат на маленьком Е.

short s = (short)i; 
short s = *(short*)&i; 

На большой порядок байтов процессора, самые высокие адреса являются наименее значимых бит, 68000 и Power PC сделать это следующим образом (на самом деле Power PC может быть как , но КПП машины от компании Apple использовать bigE)

Они дают тот же результат на большом Е.

short s = (short)i; 
short s = ((short*)&i)[1]; // (assuming i is 4 byte int) 

Итак, как вы можете видеть, немного обратный порядок байт позволяет получить на лугах t значащих бит операнда , не зная, насколько велика. мало E имеет преимущества для сохранения обратной совместимости.

Так в чем преимущество большого эндиана? Он создает шестнадцатеричные дампы, которые легче читать.

Действительно, инженеры из Motorola считают, что облегчение бремени шестнадцатеричных дампов было более важным, чем обратная совместимость. Инженеры Intel поверили противоположному.

+0

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

+0

@Josef: Да, я уверен, что было много причин, почему малое предпочтение от E было предпочтительным разработчиками аппаратного обеспечения, и совместимость, возможно, была не такой важной для них. Но, оказывается, это очень важно при переходе с 80886 на 286/386. код, написанный для 8088, по-прежнему работает на современных процессорах x86/x64. –

+0

Да, архитектуры x86 обратно совместимы на двоичном уровне, по дизайну (для хорошего и плохого), всегда сохраняя весь набор команд предыдущих поколений. По общему признанию, это граничит с моей областью знаний, но мало помогает в этой области, кроме, возможно, немного упрощает логику схемы для инструкций mov? У вас все еще есть разные коды операций для разных размеров данных (байт, слово, слово и т. Д.). –

2
  1. Да. Когда вы конвертируете значения, вам не нужно беспокоиться о контенте.

  2. Да. Когда вы конвертируете указатели, вы это делаете.

+0

И, по сути, единственный раз, когда вам когда-либо понадобится конвертировать указатели таким образом, что это имеет значение, - это сериализация данных (т. Е. Файлов или сетевых операций ввода-вывода). Но в этом случае вам действительно нужно беспокоиться, так как читатель может использовать другую сущность. –

1

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

Если в первом вопросе вы имеете в виду что-то вроде этого:

int i = ...; 
short s = (short)i; 

тогда да, s будет содержать младшие байты (ы) i.

Я думаю, что ответ на ваш второй вопрос также да; на уровне байтов вступает в действие конечность системы.

1

Вы должны знать, что ваш второй пример

int i = some_number; 
short s = *(short*)&i; 

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

Используйте союзы для этого:

union { 
    int i; 
    short s; 
} my_union; 

my_union.i = some_number; 
printf("%d\n",my_union.s); 

Кроме того, как другие отметили, вы не можете предположить, что ваш Интс будет 4 байта. Лучше использовать int32_t и int16_t, когда вам нужны конкретные размеры.

+0

Как это нарушает строгий псевдоним? – 2010-02-11 21:35:27

+1

Запись на одного члена профсоюза и чтение от другого - UB. – dalle

+0

Это не нарушение наложения. он просто подрывает систему типов, она на самом деле не создает указатель. –

1

Если вы действительно хотите, чтобы преобразовать Int на короткий, то просто сделать:

short int_to_short(int n) { 
    if (n < SHRT_MIN) return SHRT_MIN; 
    if (n > SHRT_MAX) return SHRT_MAX; 
    return (short)n; 
} 

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

+0

Я не волнуюсь, мне было просто любопытно, каким будет результат. –

Смежные вопросы