На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> char и unsigned char
    Не могу найти простую вещь :(
    чем отличаются char и unsigned char
    и как можно сделать преобразование?
      char - значение от -128 до 128, а unsigned char - от 0 до 256. Преобразуется по-моему обычным преобразованием типов.
      ExpandedWrap disabled
        <br>char c;<br>unsigned char uc;<br>.<br>.<br>.<br>uc = (unsigned char) c;
        спасибо тебе, добрый друг.
          краткое дополнение...
          "unsigned" в переводе с английского "беззнаковое"... Это так, на всякий случай...
            Цитата Pourtous, 03.08.03, 01:24:33
            char - значение от -128 до 128, а unsigned char - от 0 до 256. Преобразуется по-моему обычным преобразованием типов.
            ExpandedWrap disabled
              <br>char c;<br>unsigned char uc;<br>.<br>.<br>.<br>uc = (unsigned char) c;


            Надо еще добавить, что коррекно работает при c >= 0.
              Цитата e-yes, 03.08.03, 04:07:41
              Надо еще добавить, что коррекно работает при c >= 0.

              ты не прав... смотри:
              ExpandedWrap disabled
                char c = -125;<br>unsigned char u = (unsigned)c;


              что у нас ща в u? Правильно, 131 ;)
              т.е. если c < 0, то
              ExpandedWrap disabled
                u = 256 + c;

              ;D
                Проектировать надо нормально, тогда и компилироваться все будет без ворнингов и явного преобразования типов.
                Сантех, ты хоть и модератор, но пофлеймить любишь... мама не горюй ;D

                  2Pourtous:
                  1) Один байт может хранить значения от -128 до 127 (а не до 128).
                  2) Является ли char знаковым или беззнаковым, зависит от реализации.
                  3) Никакого явного преобразования не надо.
                  Собственно происто char отличается от unsigned char и signed char тем, что два последних являеются гарантированно беззнаковым и знаковым типом соответственно. А насчет первого этого неизвестно.
                  Сообщение отредактировано: Relan -
                    Цитата Relan, 03.08.03, 21:59:16
                    3) Никакого явного преобразования не надо.

                    Без явного преобразования будет ворнинг при компиляции.
                      typedef спасет отцов русской демократии, ну и его экстремумы через define можно наопределять...
                        Цитата e-yes, 04.08.03, 07:00:25

                        Без явного преобразования будет ворнинг при компиляции.

                        Ни gcc, ни мелкомягкий ворнинга не выдали.
                          должен быть ворнинг, мол перевод ансигнет ту сигнет...

                          ЗЫ
                          Тема, имхо, уже исчерпано, а флэйм тока развиваеЦа... имхо, тему мона закрыть!
                            Цитата SUnteXx, 04.08.03, 18:39:04
                            ЗЫ
                            Тема, имхо, уже исчерпано, а флэйм тока развиваеЦа... имхо, тему мона закрыть!
                            Не уверен... Кто-то утверждал, не помню кто, что стандарт не определяет атомарный тип ни как signed ни как unsigned, иначе получается явный избыток в терминологии (тип, signed тип и unsigned тип)...
                              Цитата SVK , 04.08.03, 18:51:57

                              Не уверен... Кто-то утверждал, не помню кто, что стандарт не определяет атомарный тип ни как signed ни как unsigned, иначе получается явный избыток в терминологии (тип, signed тип и unsigned тип)...

                              Стандарт утверждает буквально следующее (п. 3.9.1):
                              Существует три разных типа - char, signed char и unsigned char. Они имеют один и тот-же размер, подчиняются одним и тем-же правилам выравнивания и представляют по сути один и тот же объект. Для беззнакового типа все биты используются для представления числа, для знакового - один бит выделяется для знака. Тип char может быть либо знаковым, либо беззнаковым и это implementation-defined для конкретного компилятора. При этом он не является синонимом ни одного, ни другого.
                              Сообщение отредактировано: Flex_Ferrum -
                                char - используется для строковых переменных (нуль-терминированных), размер буфера определяется, например, strlen-ом.
                                unsigned char - для бинарных данных, необходимо всегда знать размер данных в буфере.
                                привести тип char  к типу uchar можно безопасно.  Обратное приведение "чревато боком" :).
                                для приведения бинарных данных к читабельному виду используют, обычно, хексодецимальное преобразование :), когда каждый uchar байт представлен двумя char байтами. (например, чтобы напечатать цифровую подпись...)
                                  Цитата Andy_KZ, 05.08.03, 11:40:12
                                  char - используется для строковых переменных (нуль-терминированных), размер буфера определяется, например, strlen-ом.

                                  :o :o :o!
                                  Ну это совсем круто... :-/
                                  Хочешь сказать, это сработает? :D
                                  ExpandedWrap disabled
                                    <br>char ch;<br>int len = strlen(ch);<br>

                                  ;) ;D :P.
                                    хех, я имел ввиду массивы данных...
                                    это можно было понять из контекста, хотябы по методу strlen. Который, как известно, возвращает длину переданной ему строки...
                                      ОК :-).
                                      Кстати, unsigned char* тоже может оканчиваться нулем. Всегда же мона преобразовать uchar* в char*, а там его в strlen() запихнуть \%).
                                        Цитата byte, 05.08.03, 11:54:47
                                        ОК :-).
                                        Кстати, unsigned char* тоже может оканчиваться нулем. Всегда же мона преобразовать uchar* в char*, а там его в strlen() запихнуть \%).


                                        а что ты будешь делать, если внутри uchar* несколько НУЛЛ-ов окажется в разных местах, или других кракозяб?
                                        правильнее, ИМХО, предполагать, что uchar* не может быть приведен к char*...
                                          Дык а как ты себе такое представляешь? :) Сколько NULL-ов ты туды запихаешь, стока их и будет \%). При преобразовании не могут же возникнуть дополнительные NULL-chars... А другие "кракозябы" на strlen() не влияют \%).
                                            Andy_KZ, открою тебе маленький секрет. char*, uchar*, schar* - это просто указатели на области памяти, содержащие элементы соответствующего типа (char, uchar, schar). Это могут быть строки (null-termnated), а могут быть просто вектора однобайтовых числел. Возьмем, например, класс string. В ряде реализаций (например, в GNU) он, грубо говоря, имеет следующий вид:
                                            ExpandedWrap disabled
                                              <br>... class basic_string ...<br>{<br>//...<br>private:<br>char* data;<br>int len;<br>//...<br>};<br>

                                            При этом, сама хранимая строка нулем не заканчивается.
                                            Я к тому, что char может быть использован для null-terminated строк. В частности, строковые литералы имеют тип const char*, но это не значит, что используется только для них.
                                              ок
                                              я имел ввиду следующее:
                                              1. когда работаешь с текстовы файлом, например, удобно его загнать весь в буфер типа char* и делать там с ним что захочется :) Например - файл конфигурации для какойнить проги...
                                              2. когда работаешь с бинарным файлом, например, его лучше загонять в буфер unsigned char*. Например, сертификат клиента. И вот чтобы на бумажке распечатать , например, серийный номер этого сертификата, его необходимо привести к читабельному виду (A306FFF2120001 и так далее...). И в таком буфере этих нулей может бфть сколько угодно :). Простым преобразованием из unsigned char* к типу char* это не сделаешь... Вот и приходится преобразовывать каждый байт из uchar* в два байта char* - т.е. 0 приводтся к виду "00", а 10 - к "0А"....

                                              ЗЫ
                                              а мелкие значения в uchar это и есть кракозябы :) которые либо никак не представлены в читабельном виде, либо выводят какуюто байду...

                                              ЗЫЫ
                                              похоже, флейм начался, извините
                                                Дык какая разница, загонять файл в char* или в unsigned char* ???? Если ты его открываешь как бинарник, каждый отдельный символ преобразовывать не придеЦа \%).

                                                Можно текстовый файл загнать как в char*, так и в unsigned char*. И с бинарником то же самое...
                                                Сообщение отредактировано: byte -
                                                  можно, базару нет :)
                                                  но
                                                  когда видишь такой прототип
                                                  char *add(char *, const char*) - к символьной строке добавить символьную строку и вернуть результат как символьную строку. Результат можно напечатать с помощью printf, например.
                                                  та же байда но с unsigned-ом выглядит так: (потому, что нет гарантии что там символьные данные)
                                                  unsigned char *add(unsigned char *, int size1, unsigned const char*, int size2, int &size3);
                                                  size3 - спорный вопрос, можно не использовать, заменив на size1+size2
                                                  печатать результат такой функции с помощью printf небезопасно, имхо.
                                                    Дык нигде нету гарантии, что там символьные данные!
                                                    Это же просто указатели на память, а в памяти этой может храниться все, что угодно! Тот же самый char* может указывать на какую-нить структуру, класс, просто число!
                                                    А может содержать строку... И то же самое с unsigned char*! Он тож может указывать хрен знает куды... Так что тут нельзя конкретно сказать, что можно выводить printf'ом, а что нельзя...
                                                    Все зависит от конкретного случая, конкретных функций,  конкрентых программ...
                                                      Цитата Andy_KZ, 05.08.03, 12:47:24
                                                      можно, базару нет :)
                                                      но
                                                      когда видишь такой прототип
                                                      char *add(char *, const char*) - к символьной строке добавить символьную строку и вернуть результат как символьную строку. Результат можно напечатать с помощью printf, например.
                                                      та же байда но с unsigned-ом выглядит так: (потому, что нет гарантии что там символьные данные)
                                                      unsigned char *add(unsigned char *, int size1, unsigned const char*, int size2, int &size3);
                                                      size3 - спорный вопрос, можно не использовать, заменив на size1+size2
                                                      печатать результат такой функции с помощью printf небезопасно, имхо.

                                                      :) А если я работаю с кирилицей и хочу явно специфицировать, что char должен представлять значения в диапазоне [0, 255] (т. к. я не могу быть уверен, что в моем компиляторе char беззнаковый)?
                                                        2SUnteXx:
                                                        Ну не выдают компиляторы предупреждений при присваивании без явного преобразования знаковому char'у беззнакового или наоборот. Проверь сам.

                                                        2Flex Ferrum:
                                                        Строковые литералы в С++ имеют тип const char[], а не const char*. Это разные вещи, но преобразования между этими типами относятся к тривиальным.
                                                        ExpandedWrap disabled
                                                          <br>const char* psz = "string1";<br>const char sz[] = "string2";<br>printf("\%d \%d\n", sizeof(psz), sizeof(sz));<br>

                                                        Будет выведено 4 (размер указателя) и 8 (размер строки).
                                                          Цитата Relan, 05.08.03, 13:00:27
                                                          2Flex Ferrum:
                                                          Строковые литералы в С++ имеют тип const char[], а не const char*. Это разные вещи, но преобразования между этими типами относятся к тривиальным.

                                                          Согласен. Mea culpa.
                                                            интересно, многие ли спользуют для строковых данных (нуль-терминированных) тип unsigned char* ?, и для бинарных char*. ?

                                                            byte "
                                                            Можно текстовый файл загнать как в char*, так и в unsigned char*. И с бинарником то же самое... "

                                                            -- исключительно для удобства пользования :) :
                                                            char* - текст
                                                            unsigned char* - бинари
                                                            и всем все понятно....
                                                            Не пытаются же запихнуть бинарные данные в класс строки, их же все таки пытаются запихнуть в какойнить аррай...


                                                            Можно, конечно, все к войд со звездой свести... Но пользоваться потом этим всем...
                                                              Я часто использую char* для бинарных файлов... ::)
                                                              А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare ;).
                                                                Цитата Andy_KZ, 05.08.03, 13:19:49
                                                                интересно, многие ли спользуют для строковых данных (нуль-терминированных) тип unsigned char* ?, и для бинарных char*. ?

                                                                Я же говорю - как только нужно работать со строками, в которых если кирилица. Там желательна явная спецификация, что ты работаешь именно с unsigned char'ами. Иначе могут быть неприятные сайд-эффекты.
                                                                Цитата Andy_KZ, 05.08.03, 13:19:49

                                                                byte "
                                                                Можно текстовый файл загнать как в char*, так и в unsigned char*. И с бинарником то же самое... "

                                                                -- исключительно для удобства пользования :) :
                                                                char* - текст
                                                                unsigned char* - бинари
                                                                и всем все понятно....

                                                                Еще понятней -
                                                                ExpandedWrap disabled
                                                                  <br>typedef unsigned char* byte;<br>byte* ...;<br>

                                                                Цитата Andy_KZ, 05.08.03, 13:19:49

                                                                Не пытаются же запихнуть бинарные данные в класс строки, их же все таки пытаются запихнуть в какойнить аррай...


                                                                Можно, конечно, все к войд со звездой свести... Но пользоваться потом этим всем...

                                                                Ты хочешь сказать, что не получится? А в ряде случаев может быть удобно. Например, для организации автоматических буферов болшого размера, которые рисковано размещать на стеке.
                                                                  Цитата byte, 05.08.03, 13:24:21
                                                                  Я часто использую char* для бинарных файлов... ::)
                                                                  А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare ;).

                                                                  Почему же?
                                                                  string binary_data(buff, buff + buff_len);
                                                                  И всех делов.
                                                                    Цитата byte, 05.08.03, 13:24:21

                                                                    А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare.

                                                                    std::string не считает символ '\0' концом строки. Длина строки хранится в отдельной переменной.
                                                                      А если я говорю о CString? ;)
                                                                        Ну так написано же - C String  ;D. Зачем хотеть чего-то более?
                                                                          Цитата Flex Ferrum, 04.08.03, 20:56:42

                                                                          Стандарт утверждает буквально следующее (п. 3.9.1):
                                                                          Для беззнакового типа все биты используются для представления числа, для знакового - один бит выделяется для знака.


                                                                          Стандарт этого не утверждает. Мои пять копеек :)

                                                                            Цитата darkgraf, 06.08.03, 15:43:58

                                                                            Стандарт этого не утверждает. Мои пять копеек :)

                                                                            ??? ??? ???
                                                                            И в чем же я ошибся? Тогда уж приведи свой вариант перевода.
                                                                              Цитата Flex Ferrum, 04.08.03, 20:56:42

                                                                              Стандарт утверждает буквально следующее (п. 3.9.1):
                                                                              Для беззнакового типа все биты используются для представления числа, для знакового - один бит выделяется для знака.

                                                                              Цитата Flex Ferrum, 06.08.03, 16:40:12
                                                                              И в чем же я ошибся? Тогда уж приведи свой вариант перевода.


                                                                              В стандарте ничего не сказано про "один бит выделяется для знака".
                                                                              Конкретно, 3.9.1/1 говорит, что "все биты всех char типов участвуют в образовании значения", и "все битовые паттерны unsigned char являются числами".

                                                                              К сожалению, против "один бит выделяется для знака" работает 3.9.1/7:
                                                                              "Представление целочисленных типов должно использовать чистую двоичную систему [Пример: Стандарт допускает использование дополнение до двух, до одного и выделенный бит для знака]"
                                                                                Цитата darkgraf, 06.08.03, 17:06:08

                                                                                В стандарте ничего не сказано про "один бит выделяется для знака".
                                                                                Конкретно, 3.9.1/1 говорит, что "все биты всех char типов участвуют в образовании значения", и "все битовые паттерны unsigned char являются числами".

                                                                                В этом смысле да - мой вариант не совсем корректен.
                                                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                0 пользователей:


                                                                                Рейтинг@Mail.ru
                                                                                [ Script execution time: 0.1410 ]   [ 16 queries used ]   [ Generated: 27.06.26, 14:44 GMT ]