Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 168, средняя оценка - 4.99
toxxin
0 / 0 / 0
Регистрация: 28.04.2009
Сообщений: 118
#1

Тип char.Signed/unsigned.Отличие типов данных. - C++

30.08.2009, 22:17. Просмотров 22463. Ответов 51
Метки нет (Все метки)

Вопрос немного может быть не туда... Прошу прощения. Пишу прошивку к контроллеру, на С. Интересует отличие типов данных. ДОпустим есть тип char и тип unsigned char. Первый -128...127, а второй 0...255 соответственно. Оба типа занимают 8 бит. В чем разница?? Или разница в обработки типов библиотеками(к примеру) или правильном распозновании например кодировки ASCII ну и т.д. Интересует разница на битовом уровне. Т.е. по идее и там и там 8 бит..

Вопрос появился, когда мне необходимо было считать байт из регистра. Для этого я завел переменную(допустим t) типа char, считал байт. Если я правильно понимаю t фактически это тоже байт памяти, поэтому при считывании регистра в эту переменную t у меня все эти 8 бит просто дублируются. Вопрос что бы изменилось если бы я переменную обозначил типа unsigned char?? И вообще пишут что тип char это символ, а мне не очень понятно ГДЕ/ЧТО/КАК этот символ. И как СИМВОЛ отличается от типа ИНТЕДЖЕР например(кроме того что int - 16 бит)??
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.08.2009, 22:17
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Тип char.Signed/unsigned.Отличие типов данных. (C++):

Значения типов данных (signed, unsigned, char) - C++
Програмирую я месяца два,но не понимаю значения типов данных : signed, unsigned, char...Помогите..

Надо перевести переменную типа unsigned char* в signed int и обратно - C++
у меня есть переменная типа unsigned char*, мне нужно перевести ее в signed int , провести арифметические вычисления и затем перевести ее...

Приведение типов unsigned char[2] to unsigned char [64] - C++
Добрый день! Подскажите пожалуйста, как поступить. Есть простая функция main int main() { SHA1Context sha; uint8_t...

8-битовый тип signed char может представлять значения от -128 до 127 - C++
8-битовый тип signed char может представлять значения от -128 до 127 Кто может растолковать как это понимать, от 128 до 127 -...

Signed/Unsigned - C++
Здравствуйте! Стал изучать ЯП C. Не совсем могу понять, что означает Signed и Unsigned (как я понял означает наличие знака(+ либо -) или...

Сравнение чисел unsigned и signed - C++
Результат: 60000 и -5536. По какому принципу выводится значение, если заданное число выходит из диапазона, как в коде? Диапазоны:...

51
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
08.11.2010, 11:20 #31
Цитата Сообщение от norge_goth Посмотреть сообщение
то есть, как я понимаю компилятор ставит какой-то признак что число беззнаковое или знаковое и использует этот признак когда нужно перевести в 10-ную систему счисления?
еще вопрос - этот признак это просто бит? и где он храниться?
Компилятор просто (ну то есть не совсем просто)) гененрирует ассемблерный код, а там уже за знак овечает флаг SF (signed flag) (флаг - это отдельный бит в регистре флагов) и вычесления уже зависят от того - выставлен ли этот флаг. К слову сказать SF устанавливается всегда, когда старший бит равен 1, например:
C
1
2
3
unsigned char a=100;
unsigned char b=28;
unsigned char c=a+b;
результатом будет c=128 (что в двоичном виде 10000000), казалось бы мы оперируем с беззнаковым типом, но флаг SF все равно будет равен 1 (старший бит же 1), т.е. как будто результат "-128" . И тут встает вопрос :" Что за бред, как процессор вообще определяет где число со знаком, а где без?", ответ:" НИКАК"! Процессор вообще не знает, что такое знак числа, он просто вычесляет то, что в него сунули, при этом результат в шестнадцатиричном виде все равно будет правильный как для положительного, так и для отрицательного числа) А для вывода на экран "знаковых отрицательных" чисел используется дополнительный код (за его существование уже ответственен компилятор, который считывает текстовый файл исходника и видит, что число со знаком, и добавляет тот самый код)
Вот, вроде объяснил) Если что не понятно, спрашивайте!

Добавлено через 5 минут
про дополнительный код:
не буду приводить код на АСМе, вот его суть на C :
C
1
2
3
4
// на это месте уже программа уже знает, что речь идет о "знаковом" числе
if (SF==1)
   printf("-");
//а далее простой перевод из HEX в DEC
т.е. знак "-", который мы видем на экране - это всего лишь отдельно напечатанный символ '-' и не более того.
1
Mr.X
Эксперт С++
3049 / 1694 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
08.11.2010, 15:13 #32
Цитата Сообщение от easybudda Посмотреть сообщение
Mr.X, вот по этому Господь дал нам константу CHAR_BIT, определённую в файле limits.h или одном из его включённых файлов
Значение CHAR_BIT зависит от реализации. Во многих источниках сказано, что это значение не может быть меньше восьми, но в стандарте C++ я что-то никаких упоминаний о значении CHAR_BIT не нашел.
1
fasked
Эксперт С++
4942 / 2522 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
08.11.2010, 15:17 #33
Цитата Сообщение от Mr.X Посмотреть сообщение
Значение CHAR_BIT зависит от реализации. Во многих источниках сказано, что это значение не может быть меньше восьми, но в стандарте C++ я что-то никаких упоминаний о значении CHAR_BIT не нашел.
Как собственно никто и не говорил, что в байте 8 бит. Аналогично то есть.
0
easybudda
Модератор
Эксперт CЭксперт С++
9664 / 5614 / 952
Регистрация: 25.07.2009
Сообщений: 10,778
08.11.2010, 17:04 #34
Цитата Сообщение от Mr.X Посмотреть сообщение
Значение CHAR_BIT зависит от реализации.
Ну да. Вот по этому лучше использовать его, если есть сомнения по поводу количества бит в байте.
0
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
08.11.2010, 18:56 #35
Цитата Сообщение от Kastaneda Посмотреть сообщение
А для вывода на экран "знаковых отрицательных" чисел используется дополнительный код (за его существование уже ответственен компилятор, который считывает текстовый файл исходника и видит, что число со знаком, и добавляет тот самый код)
спасибо вам большое все ясно даже вопросов не осталось, из понятого для себя псевдокод составил, буду рад если вы поправите если что не так :
ch = word_1 + word_2 =>

C
1
2
3
4
5
6
7
8
9
10
11
if (word_1 < 0) доп.код(word_1); // если перед числом есть минус берем доп.код
if (word_2 < 0) доп.код(word_2); // если перед числом есть минус берем доп.код
ch = word_1 + word_2;
if (Type(ch) == signed) {
      if (SF == 1) {
             printf("-");
             printf(toDec(доп.код(ch)));
      }
      else printf(toDec(ch));
}
else printf(toDec(ch));
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
09.11.2010, 10:51 #36
Цитата Сообщение от norge_goth Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
10
11
if (word_1 < 0) доп.код(word_1); // если перед числом есть минус берем доп.код
if (word_2 < 0) доп.код(word_2); // если перед числом есть минус берем доп.код
ch = word_1 + word_2;
if (Type(ch) == signed) {
      if (SF == 1) {
             printf("-");
             printf(toDec(доп.код(ch)));
      }
      else printf(toDec(ch));
}
else printf(toDec(ch));
Нет, не так. Доп.код про который я писал нужен лишь для вывода числа на экран (ну или куда там). Соответственно в этих строках он не нужен:
C
1
2
if (word_1 < 0) доп.код(word_1); // если перед числом есть минус берем доп.код
if (word_2 < 0) доп.код(word_2); // если перед числом есть минус берем доп.код
два байта и так правильно суммируются, не зависимо от знака (точнее они вообще знака не имеют, об этом писалось выше)
C
1
2
3
4
5
if (Type(ch) == signed) {
      if (SF == 1) {
             printf("-");
             printf(toDec(ch));//почему у вас тут было написано доп.код??
      }
может вы не совсем поняли что есть доп.код?
вот как это выгдядет на ассемблере (создатели компиляторов закладывают подобный код для вывода чисел, ну может более проффесионально написан, хотя этот тоже не плох)
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
43
44
45
46
OutInt proc
        
;; Проверяем число на знак.
       test    ax, ax
       jns     oi1 ; если флаг SF равен 0, то прыг на метку oi1
 
;; Если оно отрицательное, выведем минус и оставим его модуль.
       mov  cx, ax
       mov     ah, 02h
       mov     dl, '-'  ; Вот о чем я говорил, символ '-' печатается отдельно 
                        ;и не имеет отношения  к самому числу
       int     21h
       mov  ax, cx
       neg     ax
;; Количество цифр будем держать в CX.
oi1:  
        xor     cx, cx
        mov     bx, 10 ; основание сс. 10 для десятеричной и т.п.
oi2:
        xor             dx,dx
        div     bx
; Делим число на основание сс. В остатке получается последняя цифра.
; Сразу выводить её нельзя, поэтому сохраним её в стэке.
        push    dx
        inc     cx
; А с частным повторяем то же самое, отделяя от него очередную
; цифру справа, пока не останется ноль, что значит, что дальше
; слева только нули.
        test    ax, ax
        jnz     oi2
; Теперь приступим к выводу.
        mov     ah, 02h
oi3:
        pop     dx
; Извлекаем очередную цифру, переводим её в символ и выводим.
 
        add     dl, '0'
        int     21h
; Повторим ровно столько раз, сколько цифр насчитали.
        loop    oi3
        
        ret
 
OutInt endp 
 
;код взят здесь : [url]http://www.cyberforum.ru/assembler/thread54461.html[/url]
Автор кода (Goodwin98) по-моему достаточно прокоментировал его, даже не зная АСМа можно понять логику его работы, я там только пару своих коментариев добавил. (строка 5,10)
Если еще остались вопросы - спрашивайте, отвечу (если смогу)))
0
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
09.11.2010, 21:09 #37
Цитата Сообщение от Kastaneda Посмотреть сообщение
может вы не совсем поняли что есть доп.код?
немного запутался... давайте по порядку задачу разделим на 2 этапа:
1. это получение числа (например ch = -20 - 30)
2. вывод на экран

1. я так понимаю все сводиться к прибавлению и мы получаем
ch = -20 + (- 30) и АЛУ выполняет вот такие действия
ch = 11101100(-20 в доп. коде) + 11100010(-30 в доп. коде) я правильно понимаю?

и в итоге на выходе процессора мы получаем 11001110
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
10.11.2010, 14:33 #38
Цитата Сообщение от norge_goth Посмотреть сообщение
немного запутался... давайте по порядку задачу разделим на 2 этапа:
1. это получение числа (например ch = -20 - 30)
не совсем понял, что имелось ввиду, все вычесления производятся там, где они есть в сишном коде, вышепреведенный код используется только для вывода числа на печать.
ch = 11101100(-20 в доп. коде) + 11100010(-30 в доп. коде) я правильно понимаю?

и в итоге на выходе процессора мы получаем 11001110
тут тоже не понял, что значит "(-20 в доп. коде) ", что вы подразумеваете под доп.кодом?
Давайте сначала: речь изначально шла о знаковых/беззнаковых типах. Так вот - таких типов нет, они существуют только в контексте языков C/C++ (ну о других мы сейчас просто не говорим), в действительности же их нет. В языках C/C++ это просто условность для удобства работы программиста (ну и потому что программист не имеет контроля над процессом вывода на устройство вывода)
Таким образом вот этот код:
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
;; Количество цифр будем держать в CX.
;oi1:  
        xor     cx, cx
        mov     bx, 10 ; основание сс. 10 для десятеричной и т.п.
oi2:
        xor             dx,dx
        div     bx
; Делим число на основание сс. В остатке получается последняя цифра.
; Сразу выводить её нельзя, поэтому сохраним её в стэке.
        push    dx
        inc     cx
; А с частным повторяем то же самое, отделяя от него очередную
; цифру справа, пока не останется ноль, что значит, что дальше
; слева только нули.
        test    ax, ax
        jnz     oi2
; Теперь приступим к выводу.
        mov     ah, 02h
oi3:
        pop     dx
; Извлекаем очередную цифру, переводим её в символ и выводим.
 
        add     dl, '0'
        int     21h
; Повторим ровно столько раз, сколько цифр насчитали.
        loop    oi3
        
        ret
подставляется всегда, когда нужно вывести число на экран, если же компилятор увидит в сишном исходнике, что речь идет о "знаковых" типах, то плюс к этому коду он еще добавит вот этот:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
;; Проверяем число на знак.
       test    ax, ax
       jns     oi1 ; если флаг SF равен 0, то прыг на метку oi1
 
;; Если оно отрицательное, выведем минус и оставим его модуль.
       mov  cx, ax
       mov     ah, 02h
       mov     dl, '-'  ; Вот о чем я говорил, символ '-' печатается отдельно 
                        ;и не имеет отношения  к самому числу
       int     21h
       mov  ax, cx
       neg     ax
этот код нужен только для печати числа, для математических операций он не нужен, в шестнадцатиричном виде (которым оперирует ассемблер) и так посчитает все правильно, например:
C
1
int result = 30 - (-40);
вот число со знаком, и кажется,что компилятор должен обработать эту строку и в соответствии с правилами математики нужно поменять операцию с '-' на '+' и поменять знак второго операнда, но этого не будет, числа останутся в таком виде в каком есть
Код
30 = 1E (в шестнадцатиричном виде)
-40 = D8 (как и 216(dec)=D8(hex))
result = 1E - D8
вот тут может закипеть мозг, ведь 30-(-40) это 70, а 30-216 это -186. И как процессор должен понять, какой ответ ему нужен??? НИКАК
резюмируем вышесказнное
Код
имеем 30 - (-40) = 70
еще 30 - 216 = -186
эти две строки выглядят одинаково в шестнадцатиричном виде 1E - D8 = 46 

проверяем ответ:
 70 dec = 46 hex
-186 dec = 46 hex
ответ правильный для любых чисел (-40 или 216)
далее в сишном коде например
C
1
printf("&d",result);
так какой же ответ вывести? Очень просто, если result объявлен как int (что по умолчнию подразумевает signed), то числа 30 и -40 будут итерпретироватся как числа со знаком, и для вывода будет сгенерирован весь показный выше асемблерный код (т.е. с проверкой на знак и выводом символа '-' если нужно), если же result был объявлен как unsigned int, то будет сгенерирован только код получения числа (без проверки на знак) и выводом его на экран. Таким образом будет выведен правильный ответ!
Вроде объяснил
2
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
10.11.2010, 18:52 #39
Такой вопрос:

В первом случае(1) печатается символ, а во втором(2) код символа.
Что в данном случае означает unsigned?

C++
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
#pragma once
#include <iostream>
using namespace std;
class Bin
{
    unsigned char Bxbit1:1;  //        (1)
        //и т.д.
        
       //unsigned Bxbit1:1;         //        (2)
    
public:
    void ShowBin(void)
        {
       cout<<Bxbit1<<endl;
    }
};
class Hex
{//код
};
class Oct
{
//код
};
union MyByte
{
    unsigned char c;
    Bin b;
    Hex h;
    Oct o;
    MyByte(char x);
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    MyByte byte(0x1f);
    byte.b.ShowBin();
    return 0;
}//endmain
0
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
10.11.2010, 19:55 #40
Цитата Сообщение от st_dent Посмотреть сообщение
Что в данном случае означает unsigned?
дело в том если unsigned то все символы будут попадать в диапазон 0..255, а если signed то если вывести код символа(сконвертировать в инт
или Сишный printf("%d", ch)), то символы код которых больше 127 будут отрицательными -128..127
еще важный момент - помните что char это фактически однобайтовый int и символы храняться в нем в виде кодов(в кодировке ASCII)

Добавлено через 12 минут
Вопрос по вашему коду, что это за объявление? то есть что это символ/код
Цитата Сообщение от st_dent Посмотреть сообщение
unsigned char Bxbit1:1
Добавлено через 11 минут
Цитата Сообщение от Kastaneda Посмотреть сообщение
Вроде объяснил
все понятно спасибо вам большое за терпение
над наверно с асмом побаловаться чтоб меньше таких вопросов стояло
0
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
10.11.2010, 19:59 #41
Цитата Сообщение от norge_goth Посмотреть сообщение

Добавлено через 12 минут
Вопрос по вашему коду, что это за объявление? то есть что это символ/код
unsigned char Bxbit1:1
битовые поля
объявлена переменная (Bxbit1) типа (unsigned char) размером 1 бит(:1).
при таком объявлении cout выводит символ, а вот если объявить unsigned Bxbit1:1, то выводить будет код символа(точнее, числовое значение переменной:1 или 0, что и нужно в данном случае).
Вопрос как раз в том, что значит такое объявление, что это за тип - unsigned?
1
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
10.11.2010, 20:03 #42
Цитата Сообщение от st_dent Посмотреть сообщение
unsigned
без знаковый это значит что в одном байте можно поместить от 0 до 255 значение, то есть он содержит только натуральные числа(не отрицательные), signed напротив -127..128
1111 1111 = 255(unsigned)
1111 1111 = -1 (signed)

вообще unsigned это не тип а модификатор типа может быть unsigned int, unsigned char, unsigned double
а если просто как в вашем объявлении то под unsigned подразумеваеться неявно unsigned int(то есть число, а не символ для cout), тоже было бы если б вы объявили просто short или long
0
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
10.11.2010, 20:08 #43
norge_goth, спасибо, но это понятно.
объявление знакового/без знакового:
C++
1
2
unsigned int x;
signed int x;//(или просто int x, т.к. по умолчанию идет signed )
а вот что значит такое объявление??
C++
1
unsigned x;
что это за тип? тут по умолчанию int подставляется или как?
0
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
10.11.2010, 20:10 #44
Цитата Сообщение от st_dent Посмотреть сообщение
norge_goth, спасибо, но это понятно.
объявление знакового/без знакового:
C++
1
2
unsigned int x;
signed int x;//(или просто int x, т.к. по умолчанию идет signed )
а вот что значит такое объявление??
C++
1
unsigned x;
что это за тип? тут по умолчанию int подставляется или как?
оно самое
C++
1
unsigned x;
==(неявно)

C++
1
unsigned int x;
0
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
10.11.2010, 20:13 #45
norge_goth, в таком случае почему код, приведенный выше, при объявлении по разному дает разный результат, если такие объявления эквивалентны?
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.11.2010, 20:13
Привет! Вот еще темы с ответами:

Comparison between signed and unsigned integer expressions - C++
Много вот таких варнингов: Comparison between signed and unsigned integer expressions FreeBSD 10 gcc 4.8 Ввожу:gmake libthecore...

Типы данных - где нужно использовать char, а где unsigned char? - C++
Всем привет! У меня вопрос, искал ответ на него, но безуспешно. Вопрос следующий: есть два типа char и unsigned char. Я понимаю, что в...

[C++ Warning] Unit1.cpp(24): W8012 Comparing signed and unsigned values - C++
Код : #include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;string&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; using namespace std; ...

Разница между char и signed char - C++
Не понимаю в чем разница между char и signed char, ведь char по умолчанию знаковый. Не комплилируется следующий фрагмент кода: void...


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

Или воспользуйтесь поиском по форуму:
45
Yandex
Объявления
10.11.2010, 20:13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru