Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как правильно прочитать 16-бит из char?


Автор: RYB 23.5.2007, 21:26
Я сейчас работаю с hex-кодом ФАТ 12 и для того чтобы узнать где находится начало файла мне нада прочитать 2 байта, начиная с 26-го байта записи.
Я пробовал работать с инт и чар, но в первом случае числа получаються астрономическими, а если с чаром, то просто 1-байтовыми(а мне нада 2 байта). smile 

Вобщем я понял как приобразовить чар в 2байта:
если дано
Код

unsigned char c=0x9B 
  (нада получить 155), то  9 * 16 + В = 155.

Сам вопрос: как разбить значение одной переменной чар в две(с1=0х9, с2=0хВ)?
 smile 

Автор: zkv 23.5.2007, 21:33
RYB, вообщето char занимает 1 байт (или 8 бит)

0x9B(16) = 10011011(2) - наблюдаем 8 бит

если вам надо разбить байт по 4 бита:
Код

char c1 = c>>4;//первая половина байта
char c2 = (c<<4)>>4;//вторая половина

Автор: archimed7592 23.5.2007, 21:34
Код
unsigned char c = 0x9B;
unsigned char c1 = c >> 4;
unsigned char c2 = c & 0x0F;

Автор: RYB 23.5.2007, 21:39
Спасибо, все дело в unsigned char: как я увидел на практике он занимает в отличии от чар 2 байта.

Автор: codelord 23.5.2007, 21:41
Цитата(RYB @  23.5.2007,  17:39 Найти цитируемый пост)
Спасибо, все дело в unsigned char: как я увидел на практике он занимает в отличии от чар 2 байта. 

c какой стати?

Автор: zkv 23.5.2007, 21:44
Цитата(RYB @  23.5.2007,  21:39 Найти цитируемый пост)
Спасибо, все дело в unsigned char: как я увидел на практике он занимает в отличии от чар 2 байта. 

а где это так?
хм, я слышал, что char может занимать и не один байт, но не сталкивался, в любом случае вы где то ошибаетесь, 0x9B - это один цельный байт, и, думаю, если char в вашем случае занимает 1 байт, то unsigned char тоже должен... 

Автор: bsa 23.5.2007, 21:48
Цитата(RYB @ 23.5.2007,  21:39)
Спасибо, все дело в unsigned char: как я увидел на практике он занимает в отличии от чар 2 байта.

sizeof(char) == sizeof(unsigned char) == 1
sizeof(short) == sizeof(unsigned short) == 2
sizeof(int) == sizeof(unsigned int) == 4
sizeof(long) == sizeof(unsigned long) == sizeof(void*) == 4 (для 32-х битных систем) или 8 (для 64-х битных)


Автор: archimed7592 23.5.2007, 21:51
bsa, я так категорично утверждал бы только относительно char... кстати char - это unsigned char или signed char...

Автор: bsa 23.5.2007, 21:59
обычно, char - это signed char. Но у компиляторов есть ключ, который char делает unsigned char.
Но в любом случае: sizeof(unsigned char) == sizeof(signed char) == sizeof(char)

Все сказанное мной справедливо для систем, разрядность которых 32 и 64 бита.

Автор: RYB 23.5.2007, 22:01
Я сделал подобный вывод так как:

если взять char c=0x9B, c=-101
unsigned char c=0x9B, c=155

+ я юзаю прогу WinHex и в окошке Data Interpreter для 0x9B:
8bit=-101
16bit=155

Автор: bsa 23.5.2007, 22:14
И что? Все правильно.
Примеры для signed char (8 бит) и signed short (16 бит):
Код
0x80  0xFF 0x00 0x01 0x7F
-128   -1    0   +1  +127

0x8000 0xFFFF 0x0000 0x0001 0x7FFF
-32768    -1     0     +1   +32767

Автор: zkv 23.5.2007, 23:01
друзья, получается я ошибаюсь здесь:
Цитата(zkv @  23.5.2007,  21:44 Найти цитируемый пост)
я слышал, что char может занимать и не один байт

и char в любом случае занимает 1 байт? Это стандарт так говорит? Откуда то ведь это осело в моей голове...

Автор: Daevaorn 23.5.2007, 23:31
Цитата(zkv @  24.5.2007,  00:01 Найти цитируемый пост)
и char в любом случае занимает 1 байт? Это стандарт так говорит?

нет. стандарт не ограничивает. ты был прав.

Автор: Fazil6 23.5.2007, 23:32
Цитата(zkv @  23.5.2007,  23:01 Найти цитируемый пост)
и char в любом случае занимает 1 байт? Это стандарт так говорит?

<sensored>
Вообще байт на конкретной платформе должен обеспечивать хранение символа ASCII

Автор: archimed7592 23.5.2007, 23:33
Цитата(bsa @  23.5.2007,  21:59 Найти цитируемый пост)
Но в любом случае: sizeof(unsigned char) == sizeof(signed char) == sizeof(char)
да с этим никто не спорит smile

Цитата(zkv @  23.5.2007,  23:01 Найти цитируемый пост)
Это стандарт так говорит?
угумс
Цитата(IS-5.3.3)
sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; the
result of sizeof applied to any other fundamental type (3.9.1) is implementation-defined.



Цитата(bsa @  23.5.2007,  21:59 Найти цитируемый пост)
Все сказанное мной справедливо для систем, разрядность которых 32 и 64 бита.
 smile

Добавлено через 41 секунду
Daevaorn, ну блин, от тя не ожидал

Автор: Fazil6 23.5.2007, 23:36
archimed7592, дело в том, что в стандарте 1 это строго говоря не 1 байт, а одна единица и в этих единицах меряются остальные типы

Автор: Xenon 23.5.2007, 23:39
Fazil6, Я так понимаю, что все в char`ах исчисляется и один char - и есть та самая 1? Это я чтобы удостовериться smile

Автор: archimed7592 23.5.2007, 23:39
Fazil6, блин, двумя предложениямии раньше
Цитата(IS-5.3.3)
The sizeof operator yields the number of bytes in the object representation of its operand.


Добавлено через 3 минуты и 15 секунд
хотя...
Цитата(IS-1.7 The C+ + memory model)
The fundamental storage unit in the C + + memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set and is composed of a contiguous sequence of bits, the number of which is implementation-defined.

Автор: Daevaorn 23.5.2007, 23:43
Цитата(archimed7592 @  24.5.2007,  00:33 Найти цитируемый пост)
угумсЦитата(IS-5.3.3)sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; theresult of sizeof applied to any other fundamental type (3.9.1) is implementation-defined.Цитата(bsa @  23.5.2007,  21:59 )Все сказанное мной справедливо для систем, разрядность которых 32 и 64 бита. Добавлено через 41 секундуDaevaorn, ну блин, от тя не ожидал

smile
Цитата(IS 3.9.1.1)

Objects declared as characters (char) shall be large enough to store any member of the implementation’s
basic character set
.

Цитата(IS 5.4.3.1)

The sizeof operator yields the number of bytes in the object representation of its operand. The operand
is either an expression, which is not evaluated, or a parenthesized type-id. The sizeof operator shall not
be applied to an expression that has function or incomplete type, or to an enumeration type before all its
enumerators have been declared, or to the parenthesized name of such types, or to an lvalue that designates
a bit-field. sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; the
result of sizeof applied to any other fundamental type (3.9.1) is implementation-defined. [Note: in particular,
sizeof(bool) and sizeof(wchar_t) are implementation-defined.69) ] [Note: See 1.7 for
the definition of byte
 and 3.9 for the definition of object representation. ]

Цитата(IS 1.7.1)

The fundamental storage unit in the C + + memory model is the byte. A byte is at least large enough to contain
any member of the basic execution character set and is composed of a contiguous sequence of bits, the
number of which is implementation-defined. 
The least significant bit is called the low-order bit; the most
significant bit is called the high-order bit. The memory available to a C + + program consists of one or more
sequences of contiguous bytes. Every byte has a unique address.

Автор: archimed7592 23.5.2007, 23:44
ставлю "+" в репу тому, кто назовёт хоть одну реально существующую систему\платформу\компилятор, где byte не 8-ми битный smile

Добавлено @ 23:51
Daevaorn, что у тебя за стандарт такой, где есть пункт 1.7.1? smile 

насчёт же реальных систем... вот, советую: http://www.viva64.com/articles/20%20issues%20of%20porting%20C++%20code%20on%20the%2064-bit%20platform.pdf
http://rsdn.ru/article/mag/200701/XXtraps64bit.xml

вот к примеру оттуда я узнал, что на windows-64 sizeof(long)!=sizeof(void *), bsa, как видишь, не для всех справедливо smile

Автор: Daevaorn 23.5.2007, 23:55
Цитата(archimed7592 @  24.5.2007,  00:44 Найти цитируемый пост)
что у тебя за стандарт такой, где есть пункт 1.7.1? 

Цитата

ISO/IEC
14882
Second edition
2003-10-15

Вроде самый последний на сегоднешний момент.

Автор: archimed7592 23.5.2007, 23:59
Цитата(Daevaorn @  23.5.2007,  23:55 Найти цитируемый пост)
Вроде самый последний на сегоднешний момент. 
ну ещё есть драфт... но в последнем драфте уж больно много новшевств, что порой начинаешь сверяться с Second Edition smile

ммм... всегда думал, что циферки слева от текста - это так, для красоты smile а это подпункты, видимо?

Автор: Daevaorn 24.5.2007, 00:02
Цитата(archimed7592 @  24.5.2007,  00:59 Найти цитируемый пост)
ммм... всегда думал, что циферки слева от текста - это так, для красоты  а это подпункты, видимо?

это номер стиха видимоsmile каждый абзац нумеруется.

Автор: Fazil6 24.5.2007, 00:02
Цитата(Xenon @  23.5.2007,  23:39 Найти цитируемый пост)
Fazil6, Я так понимаю, что все в char`ах исчисляется и один char - и есть та самая 1? Это я чтобы удостовериться

да. Страуструп п.4.6

Автор: Xenon 24.5.2007, 00:03
Fazil6, Вот я оттуда и вспомнил smile

Автор: archimed7592 24.5.2007, 00:15
ок, а есть какой-нибудь стандартный способ узнать сколько бит содержится в "байте"? smile

Автор: Daevaorn 24.5.2007, 00:20
можно попробовать проанализировать результат нужного numeric_limits

Автор: archimed7592 24.5.2007, 00:50
ммм... написал уже темплейт, считающий log2 в compile-time, когда до меня дошло, что в numeric_limits min и max - это ф-ции smile ну и там же, рядом нашел digits... анализовать ничо и не надо smile
Код
std::numeric_limits< unsigned char >::digits


тогда ещё вот проблемака: как узнать endianity (big-endian, low-endian)? compile-time, разумеется...

Автор: Daevaorn 24.5.2007, 00:56
Цитата(archimed7592 @  24.5.2007,  01:50 Найти цитируемый пост)
low-endian)

а такой есть? может little?smile

Автор: nickless 24.5.2007, 18:44
Цитата(archimed7592 @  23.5.2007,  23:50 Найти цитируемый пост)
как узнать endianity (big-endian, low-endian)? compile-time, разумеется

endianess smile 
Можно написать проверку в мейкфайле и поставить соответствующий дефайн, примерно это делается например в automake & Co

Автор: bsa 24.5.2007, 21:02
Господа, так что там насчет sizeof(char) == 1 решили? Уже не всегда? Или все-таки всегда? А то что-то вечером цитаты из стандарта плохо воспринимаются...

Автор: archimed7592 24.5.2007, 21:19
bsa, решили, что всегда, но не всегда эта единица означает один байт... точнее она означает байт в интерпретации стандарта, где он может состоять не из 8-ми бит...
напоминаю про своё обещание поставить + тому, кто назовёт хоть одну платформу\компилятор, где байт представляет из себя не 8 бит smile 

Автор: Hurricane 24.5.2007, 21:43
Цитата(archimed7592 @  24.5.2007,  13:19 Найти цитируемый пост)
bsa, решили, что всегда, но не всегда эта единица означает один байт... точнее она означает байт в интерпретации стандарта, где он может состоять не из 8-ми бит...
напоминаю про своё обещание поставить + тому, кто назовёт хоть одну платформу\компилятор, где байт представляет из себя не 8 бит   


Архимед, тебя что, на Гугле забанили?  smile Таких систем, оказывается, было много: 

http://en.wikipedia.org/wiki/Byte#Meanings

Только, похоже, они все уже умерли.

Автор: nickless 24.5.2007, 21:46
вот еще тут посмотри: smile 
http://en.wikipedia.org/wiki/36-bit_word_length
Цитата
C implementations on 36-bit machines use 9-bit bytes

Автор: Daevaorn 24.5.2007, 21:51
archimed7592, кто-то кажется немного ошибся, а? ;)

Автор: bsa 24.5.2007, 23:04
Что-то мне подсказывает, но программа уровня выше "hello world" на машинах, разрядность байта которых отлична от 8, будет работать несколько иначе, чем на остальных машинах. Начнем с того, что передача данных отличных от текста между 9-ти битной и 8-ми битной машинами будет представлять собой "определенную" сложность.

На сколько я понял из последней ссылки начиная с IBM System/360 (анонсированой 7 апреля 1964 г) была введена практика на использование "слов", разрядность которых является степенью двойки. В то же время http://en.wikipedia.org/wiki/C_(programming_language). Так как нынче основной софт пишется на С/С++, то можно предположить, что мало кто отважится без крайней необходимости создать платформу, разрядность байта которой будет отлична от 8 бит, так как возникнет серьезная несовместимость. Причем не только программная. Или я неправ?

Имхо, все эти выкрутасы с типами в стандарте Си ни к чему хорошему не приводят. Имхо, это был компромис. Чего только стоит sizeof(short) == sizeof(int) на 16-ти битных платформах (по крайней мере, в Borland C++ 3.1 под DOS) и sizeof(int) == sizeof(long) - на 32-х битных (windows и *nix). А что будет иметь тогда разрядность 128 или 16 бит на 128 битной платформе?

Когда создаются структуры платформонезависимых файлов приходится вводить свои типы, типа UINT32, UINT16, UINT8... Думаю, не помешало бы ввести в Си на уровне стандарта дополнительные типы, например __int8, __int16, __int32, __int16b, __int32b, __int16l, __int32l (b - означает big endian, l - little endian)... Чтобы программист без введения конфигурируемых типов гарантированно имел доступ к нужному количеству разрядов в нужной последовательности.

Автор: archimed7592 24.5.2007, 23:10
ёп-та... скока плюсов то ставить... рука отсохнет smile 

Daevaorn, я не утверждал обратного... я просто захотел услышать от людей, сталкивались ли они в реальной жизни с такими системами... я имею ввиду не в музее/интернете видели, а именно программировали под них... ну да ладно, обещание своё выполню smile

Hurricane++
nickless++

Добавлено через 13 минут и 35 секунд
Цитата(bsa @  24.5.2007,  23:04 Найти цитируемый пост)
Начнем с того, что передача данных отличных от текста между 9-ти битной и 8-ми битной машинами будет представлять собой "определенную" сложность.
для этого нужно использовать унифицированный способ сериализации/десериализации... правда, лично я, не стал бы заморачиваться и писать такую сериализовалку... что же касается существующих... boost::serialization - хз, как она с такой проблемой справится...

Цитата(bsa @  24.5.2007,  23:04 Найти цитируемый пост)
Когда создаются структуры платформонезависимых файлов приходится вводить свои типы, типа UINT32, UINT16, UINT8... Думаю, не помешало бы ввести в Си на уровне стандарта дополнительные типы, например __int8, __int16, __int32, __int16b, __int32b, __int16l, __int32l (b - означает big endian, l - little endian)... Чтобы программист без введения конфигурируемых типов гарантированно имел доступ к нужному количеству разрядов в нужной последовательности. 
такая вещь реализованна в том же boost на уровне "работает почти везде"... но, по сути, что из себя должен представлять __int8 на платформе с 9-ти битным байтом? а что __int9 на пл. с 8-ми битным байтом? тогда уж вводить __int1, __int2 и пр., но, блин, в случае, если модным станет "скока хачу, стока битов в байт и положу", толку от этих типов будет не многим больше, чем от char, short, int, long, etc... насчёт l/b-endian: эт вообще гиблое дело...

all, а вот попробуйте на секундочку представить, каково станет программировать, если даже с малой долей вероятности нельзя будет предположить кол-во бит в байте, размер short/int/long/long long/new_int_type, порядок следования байт в слове(endianess)... ну и как перспективка? ;)

Автор: nickless 24.5.2007, 23:53
Цитата(bsa @  24.5.2007,  22:04 Найти цитируемый пост)
А что будет иметь тогда разрядность 128 или 16 бит на 128 битной платформе?

Не знаю как будет на 128 битах, а с 64 уже сейчас весело, винда использует модель http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/abstract_data_models.asp, а *никс/мак - http://www.unix.org/version2/whatsnew/lp64_wp.html.
Разница между ними - в LLP64 sizeof(int) = sizeof(long) = 4, sizeof(long long) = 8, а в LP64 sizeof(int) = 4, sizeof(long) = 8, и в обоих случаях sizeof(int) != sizeof(pointer)

Цитата(bsa @  24.5.2007,  22:04 Найти цитируемый пост)
не помешало бы ввести в Си на уровне стандарта дополнительные типы, например __int8, __int16, __int32, __int16b, __int32b, __int16l, __int32l

Пожалуй было бы удобно, плохо только что очень уж много вариантов, особенно если учесть еще mixed endian и int64. smile 


Цитата(archimed7592 @  24.5.2007,  22:10 Найти цитируемый пост)
что из себя должен представлять __int8 на платформе с 9-ти битным байтом? а что __int9 на пл. с 8-ми битным байтом?

ИМХО если кто до сих пор использует такие платформы - пусть сам и мучается smile 

Цитата(archimed7592 @  24.5.2007,  22:10 Найти цитируемый пост)
ну и как перспективка?

Ужасть... smile 

Автор: archimed7592 24.5.2007, 23:56
Цитата(nickless @  24.5.2007,  23:53 Найти цитируемый пост)
если учесть еще mixed endian
я извиняюсь, а как его учесть можно? smile 
ну вот на x86 с big-endian я сделаю __int32l x = 5... и чо это будет? smile 

Автор: nickless 25.5.2007, 00:05
Цитата(archimed7592 @  24.5.2007,  22:56 Найти цитируемый пост)
а как его учесть можно?

Ну например добавить еще __int32m, __int64m итд smile А вообще он вроде тоже уже не используется.

Цитата(archimed7592 @  24.5.2007,  22:56 Найти цитируемый пост)
x86 с big-endian я сделаю __int32l x = 5

На x86 little-endian ;) Я думаю такие типы можно было бы использовать для типов, которые предпологается записывать на диск/передавать куда-нибудь. Например в порограмме везде используем нативный int, а перед записью пишем его в __int32l и компайлер сам переставляет байты как надо, а мы сидим и наслаждаемся жизнью. smile 

Автор: archimed7592 25.5.2007, 00:10
Цитата(nickless @  25.5.2007,  00:05 Найти цитируемый пост)
На x86 little-endian ;)
ну не суть ;)


Цитата(nickless @  25.5.2007,  00:05 Найти цитируемый пост)
Я думаю такие типы можно было бы использовать для типов, которые предпологается записывать на диск/передавать куда-нибудь
ради этого? сомнительная выгода... хотя чем меньше велосипедов присутствует на уровне компилятора/стандарта, тем меньше придётся их изобретать обычным смертным smile 

Автор: bsa 25.5.2007, 10:07
Цитата(nickless @ 24.5.2007, 23:53)
Разница между ними - в LLP64 sizeof(int) = sizeof(long) = 4, sizeof(long long) = 8, а в LP64 sizeof(int) = 4, sizeof(long) = 8, и в обоих случаях sizeof(int) != sizeof(pointer)
А кто сказал, что sizeof(void*) должен быть равен sizeof(int)? Имхо, отсюда все грабли лезут при портировании линуховых прог с x86 на x86_64 - то что многие были уверены в том, что sizeof(int) == sizeof(void*). А выяснилось другое: sizeof(long) == sizeof(void*).
А вот разработчики винды пошли по пути наименьшего сопротивления. Вот только не уверен, что именно он окажется более эффективным с точки зрения использования ресурсов процессора. Имхо, зачем тогда нужен тип long int, когда есть int того же размера?

Цитата(nickless @ 25.5.2007,  00:05)
Я думаю такие типы можно было бы использовать для типов, которые предпологается записывать на диск/передавать куда-нибудь. Например в порограмме везде используем нативный int, а перед записью пишем его в __int32l и компайлер сам переставляет байты как надо, а мы сидим и наслаждаемся жизнью. smile

Я именно про тоже. Нет никакого смысла в циклах и прочих внутренних вещах программы юзать всякие __int64l и __int64b. Это сильно скажется на быстродействии на "неродных" архитектурах. Но вот при формировании структур данных, записываемых в файл, такие типы очень бы пригодились.

Цитата(archimed7592 @ 25.5.2007,  00:10)
хотя чем меньше велосипедов присутствует на уровне компилятора/стандарта, тем меньше придётся их изобретать обычным смертным
Может ты имел в виду, "чем больше велосипедов присутствует на уровне компилятора/стандарта, тем меньше придётся их изобретать обычным смертным"?  smile 


Кстати. Что-то мы отвлеклись от темы, вам не кажется?  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)