Как работает неявное преобразование с подписанным символом и беззнаковым целым числом?

#include<stdio.h>
void main()
{
    unsigned x = 1;
    signed char y = -1;
    if(x  > y)
        printf("x > y");
    else if(x == y)
        printf("x == y");
    else
        printf("x < y");
    printf("\n");
    printf("%d",(signed char)x);
    printf("\n");
    printf("%d",(unsigned int)y);
}

OUTPUT:
x < y
1
-1

Я ожидал, что вывод будет x == y, так как во время сравнения знаковый символ должен быть преобразован в unsigned int? Пожалуйста, объясните мне, как x ‹ y...


person Insiyah_Hajoori    schedule 28.11.2017    source источник
comment
Пожалуйста, правильно сделайте отступ в коде. Машина (компилятор) может читать и компилировать все, что угодно, но для людей она должна иметь небольшой смысл при чтении блока текста как кода. При задании вопроса справа от текстовой области было большое оранжевое поле Как форматировать. Также была целая панель инструментов для форматирования. И кнопка [?] для справки по форматированию. И область предварительного просмотра, показывающая, как будет выглядеть ваш пост после публикации. Если вы сделаете свое сообщение ясным и продемонстрируете, что вы потратили на это время, ваши шансы на получение хороших ответов повысятся.   -  person Sourav Ghosh    schedule 28.11.2017
comment
Почему вы ожидаете, что x == y? Подпись к неподписанному не означает удаление знака   -  person Sami Kuhmonen    schedule 28.11.2017


Ответы (1)


Я ожидал, что вывод будет x == y, так как во время сравнения знаковый символ должен быть преобразован в беззнаковый int?

Ну, ты на полпути.

Когда значение -1 преобразуется (фактически повышается) в unsigned int, представление производит максимально возможное значение, представляемое типом. Следовательно, продвигаемое значение становится больше, чем x, что равно 1.

Цитирование C11, глава §6.3.1.8, Обычные арифметические преобразования

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

Уточняю, продвижение не значит, снимает подписку. Операнд (значение) со знаком рассматривается как продвинутый тип. Значение определяется из битового представления. Подробности: глава §6.3.1.3,

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


Чтобы добавить к вышесказанному, использование

printf("%d",(signed char)x);

и

printf("%d",(unsigned int)y);

не годятся. %d ожидает целочисленный тип со знаком (int) в качестве аргумента.

  • Если вы хотите напечатать значение signed char, используйте %hhd
  • Если вы хотите напечатать unsigned int, используйте %u
person Sourav Ghosh    schedule 28.11.2017
comment
Есть ли способ узнать, в какое значение оно конвертируется? Я пробовал приведение типов... - person Insiyah_Hajoori; 28.11.2017
comment
@Insiyah_Hajoori, ну, вы должны использовать правильный спецификатор формата, но тогда зачем вам это? - person Sourav Ghosh; 28.11.2017
comment
@Sourav Просто добавьте примечание о неправильном использовании printf("%d",(unsigned int)y);, и это идеальный ответ. - person user694733; 28.11.2017
comment
На самом деле, вы можете заменить Значение определяется из битового представления выдержкой из 6.3.1.3. В противном случае, если новый тип не имеет знака, значение преобразуется путем многократного добавления или вычитания единицы. больше, чем максимальное значение, которое может быть представлено в новом типе, пока значение не окажется в диапазоне нового типа. - person user694733; 28.11.2017