Из этой ссылки здесь вычислить знак целого числа
int v; // we want to find the sign of v
int sign; // the result goes here
sign = v >> (sizeof(int) * CHAR_BIT - 1);
// CHAR_BIT is the number of bits per byte (normally 8)
Если я правильно понимаю, если sizeof (int) = 4 байта => 32 бита
MSB или 32-й бит зарезервированы для знака. Таким образом, мы сдвигаемся вправо на (sizeof (int) * CHAR_BIT — 1), и все биты падают с правой стороны, оставляя только предыдущий MSB с индексом 0. Если MSB равен 1 => v, то отрицательно, иначе оно положительно.
Правильно ли мое понимание?
Если да, то может кто-нибудь объяснить, что автор имел в виду под этим подходом в зависимости от архитектуры:
Этот прием работает, потому что когда целые числа со знаком сдвинуты вправо,
значение крайнего левого бита копируется в другие биты. Крайний левый
бит равен 1, когда значение отрицательно, и 0 в противном случае; все 1 бит дает
-1. К несчастью, это поведение зависит от архитектуры.
Как это будет отличаться для 32-битной или 64-битной архитектуры?
Я полагаю, что «архитектурно-зависимая» основана на том, какие операции сдвига поддерживает процессор. x86 (16, 32 и 64-битные режимы) поддерживают «арифметический сдвиг» и «логический сдвиг». Арифметический вариант копирует верхний бит сдвинутого значения вниз по мере его смещения, логический сдвиг — нет, он заполняется нулями.
Тем не менее, чтобы компилятор не генерировал код в соответствии с:
int temp = (1 << 31) & v;
sign = v;
for(i = 0; i < 31; i++)
sign = temp | (sign >> 1);
чтобы избежать проблемы архитектуры, которая имеет ТОЛЬКО «логический» сдвиг.
Большинство архитектур имеют оба варианта, но есть процессоры, которые этого не делают. (Извините, я не могу найти ссылку, которая показывает, какие процессоры имеют и не имеют два варианта смещения).
Также могут быть проблемы с 64-битными машинами, которые не могут различить сдвиги в 64 и 32 битах и, следовательно, сдвиг в старших 32 битах от числа, а не в младший бит знака. Не уверен, существуют ли такие процессоры или нет.
Другая часть, конечно, должна определить, является ли знак для -0 в дополнении единиц на самом деле результатом «0» или «-1» в терминах знака. Это действительно зависит от того, что вы пытаетесь сделать.
Это «архитектурно-зависимый», потому что в C ++ эффект смещения вправо отрицательного значения определяется реализацией (в C он вызывает неопределенное поведение). Это, в свою очередь, означает, что вы не можете полагаться на результат, если вы не прочитали и не поняли документацию вашего компилятора о том, что он делает. Лично я бы доверял компилятору генерировать соответствующий код для v < 0 ? -1 : 0
,