char и unsigned char
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.90] |
|
|
Правила раздела Visual C++ / MFC / WTL (далее Раздела)
FAQ Раздела
Обновления для FAQ Раздела
Поиск по Разделу
MSDN Library Online
char и unsigned char
|
Сообщ.
#1
,
|
|
|
|
Не могу найти простую вещь
![]() чем отличаются char и unsigned char и как можно сделать преобразование? |
|
Сообщ.
#2
,
|
|
|
|
char - значение от -128 до 128, а unsigned char - от 0 до 256. Преобразуется по-моему обычным преобразованием типов.
![]() ![]() <br>char c;<br>unsigned char uc;<br>.<br>.<br>.<br>uc = (unsigned char) c; |
|
Сообщ.
#3
,
|
|
|
|
спасибо тебе, добрый друг.
|
|
Сообщ.
#4
,
|
|
|
|
краткое дополнение...
"unsigned" в переводе с английского "беззнаковое"... Это так, на всякий случай... |
|
Сообщ.
#5
,
|
|
|
|
Цитата Pourtous, 03.08.03, 01:24:33 char - значение от -128 до 128, а unsigned char - от 0 до 256. Преобразуется по-моему обычным преобразованием типов. ![]() ![]() <br>char c;<br>unsigned char uc;<br>.<br>.<br>.<br>uc = (unsigned char) c; Надо еще добавить, что коррекно работает при c >= 0. |
|
Сообщ.
#6
,
|
|
|
|
Цитата e-yes, 03.08.03, 04:07:41 Надо еще добавить, что коррекно работает при c >= 0. ты не прав... смотри: ![]() ![]() char c = -125;<br>unsigned char u = (unsigned)c; что у нас ща в u? Правильно, 131 ![]() т.е. если c < 0, то ![]() ![]() u = 256 + c; ;D |
|
Сообщ.
#7
,
|
|
|
|
Проектировать надо нормально, тогда и компилироваться все будет без ворнингов и явного преобразования типов.
Сантех, ты хоть и модератор, но пофлеймить любишь... мама не горюй ;D |
|
Сообщ.
#8
,
|
|
|
|
2Pourtous:
1) Один байт может хранить значения от -128 до 127 (а не до 128). 2) Является ли char знаковым или беззнаковым, зависит от реализации. 3) Никакого явного преобразования не надо. Собственно происто char отличается от unsigned char и signed char тем, что два последних являеются гарантированно беззнаковым и знаковым типом соответственно. А насчет первого этого неизвестно. |
|
Сообщ.
#9
,
|
|
|
|
Цитата Relan, 03.08.03, 21:59:16 3) Никакого явного преобразования не надо. Без явного преобразования будет ворнинг при компиляции. |
|
Сообщ.
#10
,
|
|
|
|
typedef спасет отцов русской демократии, ну и его экстремумы через define можно наопределять...
|
|
Сообщ.
#11
,
|
|
|
|
Цитата e-yes, 04.08.03, 07:00:25 Без явного преобразования будет ворнинг при компиляции. Ни gcc, ни мелкомягкий ворнинга не выдали. |
|
Сообщ.
#12
,
|
|
|
|
должен быть ворнинг, мол перевод ансигнет ту сигнет...
ЗЫ Тема, имхо, уже исчерпано, а флэйм тока развиваеЦа... имхо, тему мона закрыть! |
|
Сообщ.
#13
,
|
|
|
|
Цитата SUnteXx, 04.08.03, 18:39:04 Не уверен... Кто-то утверждал, не помню кто, что стандарт не определяет атомарный тип ни как signed ни как unsigned, иначе получается явный избыток в терминологии (тип, signed тип и unsigned тип)...ЗЫ Тема, имхо, уже исчерпано, а флэйм тока развиваеЦа... имхо, тему мона закрыть! |
|
Сообщ.
#14
,
|
|
|
|
Цитата SVK , 04.08.03, 18:51:57 Не уверен... Кто-то утверждал, не помню кто, что стандарт не определяет атомарный тип ни как signed ни как unsigned, иначе получается явный избыток в терминологии (тип, signed тип и unsigned тип)... Стандарт утверждает буквально следующее (п. 3.9.1): Существует три разных типа - char, signed char и unsigned char. Они имеют один и тот-же размер, подчиняются одним и тем-же правилам выравнивания и представляют по сути один и тот же объект. Для беззнакового типа все биты используются для представления числа, для знакового - один бит выделяется для знака. Тип char может быть либо знаковым, либо беззнаковым и это implementation-defined для конкретного компилятора. При этом он не является синонимом ни одного, ни другого. |
|
Сообщ.
#15
,
|
|
|
|
char - используется для строковых переменных (нуль-терминированных), размер буфера определяется, например, strlen-ом.
unsigned char - для бинарных данных, необходимо всегда знать размер данных в буфере. привести тип char к типу uchar можно безопасно. Обратное приведение "чревато боком" .для приведения бинарных данных к читабельному виду используют, обычно, хексодецимальное преобразование , когда каждый uchar байт представлен двумя char байтами. (например, чтобы напечатать цифровую подпись...) |
|
Сообщ.
#16
,
|
|
|
|
Цитата Andy_KZ, 05.08.03, 11:40:12 char - используется для строковых переменных (нуль-терминированных), размер буфера определяется, например, strlen-ом. !Ну это совсем круто... :-/ Хочешь сказать, это сработает? ![]() ![]() ![]() <br>char ch;<br>int len = strlen(ch);<br> ;D . |
|
Сообщ.
#17
,
|
|
|
|
хех, я имел ввиду массивы данных...
это можно было понять из контекста, хотябы по методу strlen. Который, как известно, возвращает длину переданной ему строки... |
|
Сообщ.
#18
,
|
|
|
|
ОК :-).
Кстати, unsigned char* тоже может оканчиваться нулем. Всегда же мона преобразовать uchar* в char*, а там его в strlen() запихнуть \%). |
|
Сообщ.
#19
,
|
|
|
|
Цитата byte, 05.08.03, 11:54:47 ОК :-). Кстати, unsigned char* тоже может оканчиваться нулем. Всегда же мона преобразовать uchar* в char*, а там его в strlen() запихнуть \%). а что ты будешь делать, если внутри uchar* несколько НУЛЛ-ов окажется в разных местах, или других кракозяб? правильнее, ИМХО, предполагать, что uchar* не может быть приведен к char*... |
|
Сообщ.
#20
,
|
|
|
|
Дык а как ты себе такое представляешь?
Сколько NULL-ов ты туды запихаешь, стока их и будет \%). При преобразовании не могут же возникнуть дополнительные NULL-chars... А другие "кракозябы" на strlen() не влияют \%). |
|
Сообщ.
#21
,
|
|
|
|
Andy_KZ, открою тебе маленький секрет. char*, uchar*, schar* - это просто указатели на области памяти, содержащие элементы соответствующего типа (char, uchar, schar). Это могут быть строки (null-termnated), а могут быть просто вектора однобайтовых числел. Возьмем, например, класс string. В ряде реализаций (например, в GNU) он, грубо говоря, имеет следующий вид:
![]() ![]() <br>... class basic_string ...<br>{<br>//...<br>private:<br>char* data;<br>int len;<br>//...<br>};<br> При этом, сама хранимая строка нулем не заканчивается. Я к тому, что char может быть использован для null-terminated строк. В частности, строковые литералы имеют тип const char*, но это не значит, что используется только для них. |
|
Сообщ.
#22
,
|
|
|
|
ок
я имел ввиду следующее: 1. когда работаешь с текстовы файлом, например, удобно его загнать весь в буфер типа char* и делать там с ним что захочется Например - файл конфигурации для какойнить проги...2. когда работаешь с бинарным файлом, например, его лучше загонять в буфер unsigned char*. Например, сертификат клиента. И вот чтобы на бумажке распечатать , например, серийный номер этого сертификата, его необходимо привести к читабельному виду (A306FFF2120001 и так далее...). И в таком буфере этих нулей может бфть сколько угодно . Простым преобразованием из unsigned char* к типу char* это не сделаешь... Вот и приходится преобразовывать каждый байт из uchar* в два байта char* - т.е. 0 приводтся к виду "00", а 10 - к "0А"....ЗЫ а мелкие значения в uchar это и есть кракозябы которые либо никак не представлены в читабельном виде, либо выводят какуюто байду...ЗЫЫ похоже, флейм начался, извините |
|
Сообщ.
#23
,
|
|
|
|
Дык какая разница, загонять файл в char* или в unsigned char* ???? Если ты его открываешь как бинарник, каждый отдельный символ преобразовывать не придеЦа \%).
Можно текстовый файл загнать как в char*, так и в unsigned char*. И с бинарником то же самое... |
|
Сообщ.
#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 небезопасно, имхо. |
|
Сообщ.
#25
,
|
|
|
|
Дык нигде нету гарантии, что там символьные данные!
Это же просто указатели на память, а в памяти этой может храниться все, что угодно! Тот же самый char* может указывать на какую-нить структуру, класс, просто число! А может содержать строку... И то же самое с unsigned char*! Он тож может указывать хрен знает куды... Так что тут нельзя конкретно сказать, что можно выводить printf'ом, а что нельзя... Все зависит от конкретного случая, конкретных функций, конкрентых программ... |
|
Сообщ.
#26
,
|
|
|
|
Цитата 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 беззнаковый)? |
|
Сообщ.
#27
,
|
|
|
|
2SUnteXx:
Ну не выдают компиляторы предупреждений при присваивании без явного преобразования знаковому char'у беззнакового или наоборот. Проверь сам. 2Flex Ferrum: Строковые литералы в С++ имеют тип const char[], а не const char*. Это разные вещи, но преобразования между этими типами относятся к тривиальным. ![]() ![]() <br>const char* psz = "string1";<br>const char sz[] = "string2";<br>printf("\%d \%d\n", sizeof(psz), sizeof(sz));<br> Будет выведено 4 (размер указателя) и 8 (размер строки). |
|
Сообщ.
#28
,
|
|
|
|
Цитата Relan, 05.08.03, 13:00:27 2Flex Ferrum: Строковые литералы в С++ имеют тип const char[], а не const char*. Это разные вещи, но преобразования между этими типами относятся к тривиальным. Согласен. Mea culpa. |
|
Сообщ.
#29
,
|
|
|
|
интересно, многие ли спользуют для строковых данных (нуль-терминированных) тип unsigned char* ?, и для бинарных char*. ?
byte " Можно текстовый файл загнать как в char*, так и в unsigned char*. И с бинарником то же самое... " -- исключительно для удобства пользования :char* - текст unsigned char* - бинари и всем все понятно.... Не пытаются же запихнуть бинарные данные в класс строки, их же все таки пытаются запихнуть в какойнить аррай... Можно, конечно, все к войд со звездой свести... Но пользоваться потом этим всем... |
|
Сообщ.
#30
,
|
|
|
|
Я часто использую char* для бинарных файлов... :
![]() А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare . |
|
Сообщ.
#31
,
|
|
|
|
Цитата 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* - бинари и всем все понятно.... Еще понятней - ![]() ![]() <br>typedef unsigned char* byte;<br>byte* ...;<br> Цитата Andy_KZ, 05.08.03, 13:19:49 Не пытаются же запихнуть бинарные данные в класс строки, их же все таки пытаются запихнуть в какойнить аррай... Можно, конечно, все к войд со звездой свести... Но пользоваться потом этим всем... Ты хочешь сказать, что не получится? А в ряде случаев может быть удобно. Например, для организации автоматических буферов болшого размера, которые рисковано размещать на стеке. |
|
Сообщ.
#32
,
|
|
|
|
Цитата byte, 05.08.03, 13:24:21 Я часто использую char* для бинарных файлов... : ![]() А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare .Почему же? string binary_data(buff, buff + buff_len); И всех делов. |
|
Сообщ.
#33
,
|
|
|
|
Цитата byte, 05.08.03, 13:24:21 А в класс строки ты бинарные данные корректно не запихнешь, т.к. все данные "обрубятся" на первом же NULL-chare. std::string не считает символ '\0' концом строки. Длина строки хранится в отдельной переменной. |
|
Сообщ.
#34
,
|
|
|
|
А если я говорю о CString?
|
|
Сообщ.
#35
,
|
|
|
|
Ну так написано же - C String ;D. Зачем хотеть чего-то более?
|
|
Сообщ.
#36
,
|
|
|
|
Цитата Flex Ferrum, 04.08.03, 20:56:42 Стандарт утверждает буквально следующее (п. 3.9.1): Для беззнакового типа все биты используются для представления числа, для знакового - один бит выделяется для знака. Стандарт этого не утверждает. Мои пять копеек ![]() |
|
Сообщ.
#37
,
|
|
|
|
Цитата darkgraf, 06.08.03, 15:43:58 Стандарт этого не утверждает. Мои пять копеек ![]() ??? ??? ??? И в чем же я ошибся? Тогда уж приведи свой вариант перевода. |
|
Сообщ.
#38
,
|
|
|
|
Цитата 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: "Представление целочисленных типов должно использовать чистую двоичную систему [Пример: Стандарт допускает использование дополнение до двух, до одного и выделенный бит для знака]" |
|
Сообщ.
#39
,
|
|
|
|
Цитата darkgraf, 06.08.03, 17:06:08 В стандарте ничего не сказано про "один бит выделяется для знака". Конкретно, 3.9.1/1 говорит, что "все биты всех char типов участвуют в образовании значения", и "все битовые паттерны unsigned char являются числами". В этом смысле да - мой вариант не совсем корректен. |