С Новым годом! Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/29: Рейтинг темы: голосов - 29, средняя оценка - 4.62
0 / 0 / 0
Регистрация: 22.09.2018
Сообщений: 37
1

Результат сравнения signed и unsigned

22.09.2018, 13:04. Показов 5791. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день! Помогите, пожалуйста, разобраться.
Почему при сравнении этих переменных выдает ложь:
C
1
2
char c=-5; unsigned char uc=5;    
printf("char and unsigned char -5>5 : %d\n\n", c>uc);
А здесь истину:
C
1
2
3
4
5
int i=-5; unsigned int u=5;
printf("int and unsigned int -5>5 : %d\n", i>u);
 
char c=-5; unsigned int u=5;
printf("char and unsigned int -5>5 : %d\n\n", c>u);
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.09.2018, 13:04
Ответы с готовыми решениями:

Почему результат сравнения int и unsigned int равен 1?
Почему результат сравнения в выводе равен 1? int i = -5; unsigned u = 5; printf("int...

Разобрать код с signed unsigned
Прошу помочь разобраться signed char sc; signed short int ssi; signed int si; signed long sl;...

Представление типа как signed/unsigned
Подскажите, пожалуйста, если для представления типа данных как signed отвечает старший разряд, то...

Вывод на экран значений signed от unsigned
Здравствуйте! Помогите разобраться с выводом значений signed и unsigned. Я знаю что это знаковые и...

6
1624 / 806 / 146
Регистрация: 13.06.2015
Сообщений: 3,266
22.09.2018, 14:39 2
chpokhead, все переменные типа char в Си неявно приводятся к типу int, поэтому в первом примере несоответствие знаковостей разрешается уже на этом этапе, а дальше просто сравниваются два int. В двух следующих примерах никакого неявного приведения типов не производится, и компилятор выдаёт предупреждения, что при подобном сравнении результат может получиться не тот, что надо, т.к. не знает, какое именно сравнение производить - знаковое или беззнаковое.
1
Вездепух
Эксперт CЭксперт С++
12793 / 6670 / 1795
Регистрация: 18.10.2014
Сообщений: 16,889
22.09.2018, 20:01 3
Лучший ответ Сообщение было отмечено chpokhead как решение

Решение

В первом случае выполняются integral promotions и сравнение выполняется в рамках типа int. Т.е. никакого сравнения signed и unsigned тут нет. Сравниваются два int значения: (int) c > (int) uc - разумеется ложь.

Во втором случае смешанное signed/unsigned сравнение производится в домене типа unsigned int. То есть сравниваются (unsigned int) i и u. (unsigned int) i > u - истина.

В третьем случае сначала производится integral promotion из char в int, а затем срабатывает правило из второго случая. То есть сравнивается (unsigned int) (int) c > u - истина.
1
635 / 390 / 75
Регистрация: 21.09.2008
Сообщений: 1,342
22.09.2018, 20:02 4
chpokhead, чтобы знать, что творится "за фасадом" компилятора, то можно воспользоваться его опциями, генерирующие ассемблерный листинг. Для gcc это опция -S. Первый пример на ассемблере gcc 5.1.0 выдал следующий листинг:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    .file   "uns1.c"
    .intel_syntax noprefix
    .def    ___main;    .scl    2;  .type   32; .endef
    .section .rdata,"dr"
    .align 4
LC0:
    .ascii "char and unsigned char -5>5 : %d\12\12\0"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    push    ebp
    mov ebp, esp
    and esp, -16
    sub esp, 32
    call    ___main
    mov BYTE PTR [esp+31], -5
    mov BYTE PTR [esp+30], 5
    movsx   edx, BYTE PTR [esp+31]
    movzx   eax, BYTE PTR [esp+30]
    cmp edx, eax
    setg    al
    movzx   eax, al
    mov DWORD PTR [esp+4], eax
    mov DWORD PTR [esp], OFFSET FLAT:LC0
    call    _printf
    mov eax, 0
    leave
    ret
    .ident  "GCC: (tdm-1) 5.1.0"
    .def    _printf;    .scl    2;  .type   32; .endef
Листинг второго примера:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    .file   "uns2.c"
    .intel_syntax noprefix
    .def    ___main;    .scl    2;  .type   32; .endef
    .section .rdata,"dr"
    .align 4
LC0:
    .ascii "int and unsigned int -5>5 : %d\12\0"
    .align 4
LC1:
    .ascii "char and unsigned int -5>5 : %d\12\12\0"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    push    ebp
    mov ebp, esp
    and esp, -16
    sub esp, 32
    call    ___main
    mov DWORD PTR [esp+28], -5
    mov DWORD PTR [esp+24], 5
    mov eax, DWORD PTR [esp+28]
    cmp eax, DWORD PTR [esp+24]
    seta    al
    movzx   eax, al
    mov DWORD PTR [esp+4], eax
    mov DWORD PTR [esp], OFFSET FLAT:LC0
    call    _printf
    mov BYTE PTR [esp+23], -5
    mov DWORD PTR [esp+16], 5
    movsx   eax, BYTE PTR [esp+23]
    cmp eax, DWORD PTR [esp+16]
    seta    al
    movzx   eax, al
    mov DWORD PTR [esp+4], eax
    mov DWORD PTR [esp], OFFSET FLAT:LC1
    call    _printf
    mov eax, 0
    leave
    ret
    .ident  "GCC: (tdm-1) 5.1.0"
    .def    _printf;    .scl    2;  .type   32; .endef
Как видите, Kukuxumushu был прав.
Весьма полезны в gcc две опции (-Wall -Wextra), включающие выдачу предупреждений в подозрительных местах.
0
Вездепух
Эксперт CЭксперт С++
12793 / 6670 / 1795
Регистрация: 18.10.2014
Сообщений: 16,889
22.09.2018, 20:08 5
Цитата Сообщение от Kukuxumushu Посмотреть сообщение
В двух следующих примерах никакого неявного приведения типов не производится, и компилятор выдаёт предупреждения, что при подобном сравнении результат может получиться не тот, что надо, т.к. не знает, какое именно сравнение производить - знаковое или беззнаковое.
Это не верно. Правила языка С четко говорят, что при сравнении unsigned int и int знаковый операнд неявно приводится к беззнаковому типу и сравнение делается в рамках беззнакового типа. Никакого "компилятор не знает, какое именно сравнение производить" тут нет и быть не может.

Добавлено через 5 минут
Цитата Сообщение от sharpey Посмотреть сообщение
чтобы знать, что творится "за фасадом" компилятора, то можно воспользоваться его опциями, генерирующие ассемблерный листинг. Для gcc это опция -S. Первый пример на ассемблере gcc 5.1.0 выдал следующий листинг:
Это покажет, "что творится "за фасадом" компилятора", но нисколько не прибавит вам понимания правил языка. Без предварительного понимания этих правил от разбора ассемблерных листингов будет только огромный вред и масса впустую потраченного времени. Огромное количество феерических и сюрреалистических "теорий" о языке С было высосано именно из ассемблерных листингов "пионэрами", которые почему-то решили, что они что-то там поняли.
1
635 / 390 / 75
Регистрация: 21.09.2008
Сообщений: 1,342
22.09.2018, 20:28 6
TheCalligrapher, про правила языка Вы правы. Их надо знать. Однако всё равно надо также знать, чего там написал оптимизирующий компилятор. Например, забыли про volatile и получите перемещение переменной из памяти в регистр. И в прерывании огребаем проблемы.
0
1272 / 1029 / 470
Регистрация: 25.12.2016
Сообщений: 3,333
22.09.2018, 22:26 7
И ещё я бы добавил, что в реальной программе лучше так вообще не писать, а при необходимости использовать явное приведение типов.
0
22.09.2018, 22:26
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.09.2018, 22:26
Помогаю со студенческими работами здесь

Каким бы стоило сделать тип char по умолчанию — signed или unsigned?
Появился такой вопрос: каким бы стоило сделать тип char по умолчанию - signed или unsigned?

Определение диапазонов переменных типов char, short, int и long (как signed, так и unsigned)
Вроде до этого все читал внимательно, задание понимаю, как реализовать - не знаю. С только начал...

Ошибка W8012: "Comparing signed and unsigned values"
void init() { int j; gotoxy(x,menuitem+9); MODE_8; cprintf("%s",menu_names); ...

Тип signed char и unsigned char
Есть путаница в типах данных в Си signed char и unsigned char. Если объявить переменную следующим...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru