Сдвиг влево дает мне странные результаты - PullRequest
0 голосов
/ 19 апреля 2020
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    printf("left shift 1 = %d\n", 1 << 1);
    printf("left shift 2 = %d\n", 1 << 2);
    printf("left shift 3 = %d\n", 1 << 3);
    printf("left shift 4 = %d\n", 1 << 4);
    printf("left shift 5 = %d\n", 1 << 5);
    printf("left shift 6 = %d\n", 1 << 6);
    printf("left shift 7 = %d\n", 1 << 7);

    return 0;
}

и я получил вывод, подобный следующему:

left shift 1 = 2
left shift 2 = 4
left shift 3 = 8
left shift 4 = 16
left shift 5 = 32
left shift 6 = 64
left shift 7 = 128

Это кажется правильным для чисел 1 и 2, но что случилось с другими числами от 3 до 7?

Ответы [ 3 ]

1 голос
/ 19 апреля 2020

В этом нет ничего странного. Для целого числа без знака (также обычно для целого числа со знаком, когда вы не посягаете на бит знака, но это не предписано стандартом), сдвиг влево в основном удваивает значение.

И это именно то, что вы видите:

1 << 0 = 0000 0001 =   1
1 << 1 = 0000 0010 =   2
1 << 2 = 0000 0100 =   4
1 << 3 = 0000 1000 =   8
1 << 4 = 0001 0000 =  16
1 << 5 = 0010 0000 =  32
1 << 6 = 0100 0000 =  64
1 << 7 = 1000 0000 = 128
0 голосов
/ 19 апреля 2020

Что вы испытываете, так это правильное поведение оператора сдвига.

Давайте начнем с иллюстрации десятичного представления байта:

ByteDecValue = 
    bit0 * 2^0 +
    bit1 * 2^1 +
    bit2 * 2^2 +
    bit3 * 2^3 +
    bit4 * 2^4 +
    bit5 * 2^5 +
    bit6 * 2^6 +
    bit7 * 2^7

Так, например, десятичное значение, соответствующее к байту 00010010b равно 2^4 + 2^1 = 18 dec.

Интересный конкретный сценарий возникает, когда только один байт равен 1. Получив формулу из приведенного выше, мы можем сказать

ByteDecValue_bit_N = 2^N

2^0 = 1 << 0 = 0000 0001
2^1 = 1 << 1 = 0000 0010
2^2 = 1 << 2 = 0000 0100
2^3 = 1 << 3 = 0000 1000
2^4 = 1 << 4 = 0001 0000
2^5 = 1 << 5 = 0010 0000
2^6 = 1 << 6 = 0100 0000
2^7 = 1 << 7 = 1000 0000

Это именно то, что вы испытываете: сдвигая 1 влево N раз, вы получаете одиночную 1 в позиции N, поэтому сила 2 ^ N.

Примечание: ваш тест было бы завершено путем печати также значение 1 << 0. В этом случае вы получили бы 2^0 = 1. Отсутствие сдвига означает сохранение исходного значения.

0 голосов
/ 19 апреля 2020

Операция левого сдвига n << 1 фактически умножает левый операнд на 2. И результат вашей программы показывает это.

Предположим, что у вас есть объект с именем n типа char

0000 0001

тогда n << 1 дает </p>

0000 0010 

, что в десятичной системе счисления 2

n << 2 дает </p>

0000 0100

что в десятичной записи 4

n << 3 дает </p>

0000 1000

, то есть десятичной записи 8.

и т. д.

...