Оператор отрицания на неподписанном символе - PullRequest
0 голосов
/ 26 апреля 2020
#include <stdio.h>
int main() {
    unsigned char a = 5;
    printf("%d\n",~a);
    printf("%d\n",a=~a);
    return 0;
}

В соответствии с принятым здесь ответом Отрицание внутри printf , в первом printf a должно быть переведено в int, а на выходе должно быть большое отрицательное число. Но вывод первого printf равен -6. Не могли бы вы объяснить, почему вывод равен -6 и почему в этом случае char не повышается до int?

Ответы [ 3 ]

2 голосов
/ 26 апреля 2020

Не могли бы вы объяснить, почему вывод равен -6 и почему в этом случае символ не повышается до int?

Не совсем, потому что это означает , преобразуемый в int - и, как int, инвертирует все биты (при условии двухсимвольная запись без переполнения) положительное n значение в отрицательное значение, -(n+1).

Эта модификация вашего кода может продемонстрировать, что происходит:

#include <stdio.h>
int main()
{
    int a = 5;
    printf("%d\n", ~a); // Prints -6
    printf("%d\n", a = (unsigned char)~a); // Prints 250 - lower 8 bits of the int
    return 0;
}
1 голос
/ 26 апреля 2020

Для двух дополнительных внутренних представлений, если у вас есть целочисленное значение x, тогда выражение

x + ~x + 1

равно 0.

Так что для этого объявления

unsigned char a = 5;

операнд выражения ~a будет повышен до типа int.

Таким образом, у вас будет этот

~a + a + 1 = 0

, то есть

~a + 5 + 1 = 0

И как результат значение выражения ~a

~a = -5 -1 = -6

В двоичной записи это выглядит так (при условии, что тип int занимает 4 байта)

a ( = 5 ) = 00000000 00000000 00000000 00000101
~a        = 11111111 11111111 11111111 11111010

a + ~a    = 11111111 11111111 11111111 11111111

Последнее двоичное значение является представлением -1 в типе int.

В этом вызове

printf("%d\n",a=~a);

сначала выражение ~ a было усечено до объекта типа unsigned char dues для назначения

a=~a

То есть выражение будет иметь неотрицательное число.

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

Повышается в должности и ~5 == -6 в дополнении к двум. Предполагая дополнение до двух, побитовое отрицание небольшого положительного числа приведет к небольшому отрицательному числу. Число будет большим только при просмотре как unsigned, что и делает "%X" в связанном ответе.

(Кстати, число в связанном ответе также должно быть приведено к unsigned, прежде чем печататься как "%X", потому что printf технически требует точного соответствия между спецификатором преобразования и типом переданного аргумент).

...