2016-03-13 3 views
0

Есть ли кто-нибудь, кто может помочь мне объяснить, в чем разница между неподписанным символом и char в операции XOR?unsigned char и char XOR operation

#include <stdio.h> 

int main() { 
    char a[2] = { 0x56, 0xa5 }; // a[0] 0101 0110 
           // a[1] 1010 0101 
    a[0] = a[0]^a[1];   // a[0] 1111 0011 f3 
    printf("%02x", a[0]); 
    puts(""); 

    unsigned char b[2] = { 0x56, 0xa5 }; // b[0] 0101 0110 
             // b[1] 1010 0101 
    b[0] = b[0]^b[1];     // b[0] 1111 0011 f3 
    printf("%02x", b[0]); 
    puts(""); 
} 

результат:

fffffff3 
f3 
[Finished in 0.0s] 

Другой пример:

#include <stdio.h> 

int main() { 
    char a[2] = { 0x01, 0x0a }; 

    a[0] = a[0]^a[1];   
    printf("%02x", a[0]); 
    puts(""); 

    unsigned char b[2] = { 0x01, 0x0a };  

    b[0] = b[0]^b[1];    
    printf("%02x", b[0]); 
    puts(""); 
} 

результат:

0b 
0b 
[Finished in 0.0s] 
+0

Неправильный тип переданного 'printf'. '% x' ожидает' unsigned', вы передаете 'int' – Olaf

+0

@Olaf: вы правы, но передача' (unsigned int) a [0] 'будет производить тот же вывод. По-прежнему требуется объяснение. – chqrlie

ответ

1

В первом случае ваш код

printf("%02x", a[0]); 

Передает char значение в VARIADIC функции printf. Значение char повышается до int и передается как таковое. Значение a[0] равно -13, так как тип char по умолчанию подписан в вашей среде. Значение сохраняется в расчете на int, а printf получает его как int.

Формат %02x ожидает unsigned int значение. printf передано значение int, неправильный тип, вызывающий неопределенное поведение. Так как int и unsigned int используют на платформе такое же соглашение о передаче параметров, это отрицательное значение -13 интерпретируется как unsigned int с тем же шаблоном бита со значением 0xFFFFFFF3, потому что int на вашей платформе имеет 32 бита, а отрицательные значения представлены в дополнении 2s , Строка, созданная printf, равна fffffff3. Такое поведение на самом деле не гарантируется стандартом C.

Во втором примере b[0] является unsigned char со значением 243 (0xf3).Его поощрение до int сохраняет значение, а int передано printf: 243. Такое же неопределенное поведение вызывается, так как printf передается int вместо unsigned int. В вашем конкретном случае преобразование, выполненное в printf, дает то же значение, которое печатается как шестнадцатеричное с не менее чем двумя цифрами, заполненными ведущим 0 с, дает f3.

Чтобы избежать этой неоднозначности, вы должны либо привести операнд в unsigned char:

printf("%02x", (unsigned)(unsigned char)a[0]); 

Или укажите свой реальный тип, как unsigned char:

printf("%02hhx", (unsigned char)a[0]); 
+0

Помогло ли downvoter объяснить его решение? – chqrlie

0

(тип char подписан, SizeOf (INT) составляет 4, 8 бит на байт.)

Оба операнда a, повышается до int, из-за целочисленные поощрения:

a[0]^a[1]; 

Поскольку a[1] является знаковым типом, char, число 0xa5 фактически представляет собой отрицательное значение -91. Представление значения -91 типа int - 0xffffffa5.

Итак расчет становится:

0x00000056^0xffffffa5 

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

86^-91 

В результате этой операции является: 0xfffffff3

без знака версии символа этого расчеты не есть эта «проблема».

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