[C/C++] бинарная строка --> int
char a[]={0x00,0x54,0x34,0x3F};
то после присваивания
int b = *int *) a);
в переменной b будет искомое 0x3F345400

char c[] = {0x3F, 0x34, 0x54, 0x00};
int a = c[3] + c[2]*265 + c[1]*256*256 + c[0]*256*256*256;

Но вот шестнадцатеричной записью не пользоваться - это дисреспект и фу полюбому.
+1 первонах

Надо писать как проще. Тем более, что компилятор сам разберется.
сдвиги всяко лучше. да и в циферках очепечатся можно, что Глюк и сделал собственно



Если бы была бинарная строкана некоторых архитектурах, а на других 0x0054343F
char a[]={0x00,0x54,0x34,0x3F};
то после присваивания
int b = *int *) a);
в переменной b будет искомое 0x3F345400
c[0]<<8) + c[1])<<8) + c[2])<<8) + c[3]
или
c[3] + (c[2]<<8) + (c[1]<<16) + (c[0]<<24)?
Наверное, вообще вот так:
c[3] | (c[2]<<8) | (c[1]<<16) | (c[0]<<24)
Есть char* допустим с таким бинарным содержимым: 0x3F 0x34 0x54 0x00.
Как преобразовать это дело в int чтобы получить 0x3F345400?
а как быстрее:Все хорошо, только порядок другой получается, надо поменять c[0]<->c[3], c[1]<->c[2].
c[0]<<8) + c[1])<<8) + c[2])<<8) + c[3]
или
c[3] + (c[2]<<8) + (c[1]<<16) + (c[0]<<24)?
Наверное, вообще вот так:А это вообще не работает, если c объявлено как char*. Но будет работать, если объявить как unsigned char*.
c[3] | (c[2]<<8) | (c[1]<<16) | (c[0]<<24)
Насчет скорости выполнения: надо ставить эксперименты на конкретных машинах/компиляторах.
ntohl(*long*)pch
> char a[]={0x00,0x54,0x34,0x3F};
> то после присваивания
> int b = *int *) a);
> в переменной b будет искомое 0x3F345400
Не будет.
Правильный ответ дали те, кто воспользовался сложением или поразрядными "или".
, твой ответ тоже неверен (неполон): у тебя с вероятностью 1/2 или 3/4
может случаться то, что униксоиды называют SIGBUS.
Разве что будет передаваться правильный указатель.
---
...Я работаю антинаучным аферистом...
Все хорошо, только порядок другой получается, надо поменять c[0]<->c[3], c[1]<->c[2].Шутишь? Во всех примерах c[3] не сдвигается ни на сколько, c[0] сдвигается на 24 бита. Где ошибка?
P.S. А. Заметил. Там в char* порядок не тот

может случаться то, что униксоиды называют SIGBUS.Я пользуюсь SEH, так что не должно


Чё?
---
"Расширь своё сознание!"
Распространённых архитектур всего две,да?
вот интересно узнать: какие именно две?
ntohl(*long*)pchво-первых long не обязан быть ровно 4 char-а, а в распространенном случае когда он из 8-ми char-ов это выражение выходит за границу массива,
и во-вторых это выражение нарушает т.н. strict aliasing rules, и может приводить к неверному результату при наличии некоторых сильных оптимизаций, разрешенных стандартом.
Видимо, надо выкинуть одну из этих трёх.
---
...Я работаю антинаучным аферистом...
Примеры?
во-вторых long не обязан быть ровно 4 char-а, и даже не обязан быть не менее 4 char-а (ибо char может быть более 8 бит

Хотел, кстати, написать uint32_t, но потом передумал.
> ибо "host to network", а не наоборот
Почему?
Я, наоборот, вижу, что по указателю находятся байты в сетевом порядке,
а в int надо получить родной, машинный.
Я не стал вдаваться в подробности, что int бывает 16-разрядным,
и четыре, как хочет того автор, октета в него просто так не влезут.
---
...Я работаю антинаучным аферистом...
P.S. А что, насильники разрешили char-у быть больше октета?
любая 64-битная архитектура с компилятором gcc - sizeof(long)==8*sizeof(char) - 64 бит, и уже выражениево-вторых long не обязан быть ровно 4 char-а, и даже не обязан быть не менее 4 char-а (ибо char может быть более 8 битПримеры?
*long*)pch) будет читать за границей массива из четырех char-ов, что есть потенциальный segfault.
> Во-первых в данном случае мог бы быть уместен htonl(*long*)pchсогласен,
> ибо "host to network", а не наоборот
Почему?
Я, наоборот, вижу, что по указателю находятся байты в сетевом порядке,
а в int надо получить родной, машинный.
исправился
Кстати о gcc.
Как он относится к выравниванию char? Выравнивает?
---
...Я работаю антинаучным аферистом...
Big Endian y Little Endian
Писать платформо-независимый код, который решает платформо-зависимую задачу - это жесть, респект Контре и всем остальным поучавствовавшим.
Если, блиа, в char* лежит ЧЕТЫРЕ БАЙТА, СИМВОЛИЗИРУЮЩИЕ СОБОЙ BIG-ENDIAN ИНТ, то, наверное, рассуждения на тему того, как бы их пошевелить на литтл-эндиан 64битной машине, имеют отчётливый привкус благородного безумия. Не, я понимаю, вдруг их такими по сети прислали, но всё же.
ЗЫ: В весьма большой части не-8086 архитектур инт двухбайтный, хаха.
ЗЗЫ: блайнду - респект =) Глюк жжот "int a = c[3] + c[2]*265 + c[1]*256*256 + c[0]*256*256*256;"
в смысле, лично мне встречался несколько лет подряд
sizeof(char) тождественно равен 1.разумеется, но это не означает, что char 8-битный
Писать платформо-независимый код, который решает платформо-зависимую задачу - это жесть,это не жесть, а совершенно обычная практика
всю платформозависимость обычно нетрудно скрыть в маленьком интерфейсе, если нельзя вообще без этого обойтись и опираясь на стандарт писать кроссплатформенный код.
ЗЫ: В весьма большой части не-8086 архитектур инт двухбайтный, хаха.и что?
Big Endian y Little Endianэто не две архитектуры, а 2 типа порядка байтов в числах (они действительно наиболее распространены, но тем не менее есть и другие)
а количество широко используемых архитектур исчисляется десятками
Если, блиа, в char* лежит ЧЕТЫРЕ БАЙТА, СИМВОЛИЗИРУЮЩИЕ СОБОЙ BIG-ENDIAN ИНТ, то, наверное, рассуждения на тему того, как бы их пошевелить на литтл-эндиан 64битной машине, имеют отчётливый привкус благородного безумия.И с чего же это?
Речь вообще о том, как их пошевелить на любой машине.
Очевидно ни размеры целочисленных типов рабочей платформы, ни порядок байтов в них не были указаны в условии задачи, поэтому опираться можно только на положения стандарта.
Если, блиа, в char* лежит ЧЕТЫРЕ БАЙТА, СИМВОЛИЗИРУЮЩИЕ СОБОЙ BIG-ENDIAN ИНТ, то, наверное, рассуждения на тему того, как бы их пошевелить на литтл-эндиан 64битной машине, имеют отчётливый привкус благородного безумия. Не, я понимаю, вдруг их такими по сети прислали, но всё же.в косущих бинарных протоклолах типа СМБ с этим немного весело, особенно с выравниванием.
а вот на powerpc есть спец команды для реверса байтов (код из самбы)
static __inline__ uint32_t ld_le32(const uint32_t *addr)
{
uint32_t val;
__asm__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr "m" (*addr;
return val;
}
а вот на трёшке что-то я не помню (хз, потом может что и появилось)
или есть свап байтов в слове и слов в двойном слове?
но это изврат какой-то.
видимо клали интеловцы на ИБМ, а вот ИБМ на интелов не поклала

Эт ещё фигня, мне тут знакомый рассказал, что у виртуальной жавамашыны литтлэндиан архитектура. И на PC, естественно, тоже. Поэтому процесс совокупления плюсовой и жавапроги с быстрым обменом бинарными данными выглядит довольно-таки мерзко.
а количество широко используемых архитектур исчисляется десяткамиНу так способ хранения чисел в памяти - одна из особенностей (характеристика) каждой из них, теперь представь, что по всем остальным характеристикам все широко используемые архитекруры для нас неразличимы (то есть мы переходим в одноразмерное признаковое пространство). В этом пространстве все наши архитектуры делятся на два класса:
BIg и Little Endian. Назовём всех представителей первого класса - процессорами с Биг Эндиан архитектурой, а соответсвенного второго - с Литтл. Ясно теперь тебе, что значит "Биг Эндиан Архитектруа"?
Эт ещё фигня, мне тут знакомый рассказал, что у виртуальной жавамашыны литтлэндиан архитектура. И на PC, естественно, тоже. Поэтому процесс совокупления плюсовой и жавапроги с быстрым обменом бинарными данными выглядит довольно-таки мерзко.дык у PC и есть литтл-эндиан, в чём проблема то?
странно, мне всегда казалось что у явы эндинутость максимально спрятана и соответствует хосту.
Глюк жжот "int a = c[3] + c[2]*265 + c[1]*256*256 + c[0]*256*256*256;"Я дико извиняюсь, можно мне не убивать себя об стену? Ты, если что, не первый, кто это заметил.
Ну так способ хранения чисел в памяти - одна из особенностей (характеристика) каждой из них,именно ОДНА из них
Архитектурой все же общепринято называть гораздо большую совокупность признаков, а не один единственный, упомянутый тобой. Гораздо более определяющей характеристикой архитектуры можно считать систему команд проца (спецификация и реализация которой естественным образом определяет и порядок байтов в регистровых числах, если их вообще можно логически делить на байты систему доступа к устройствам, особенно организация оперативной памяти, и т.п.
Например, некоторые архитектуры позволяют переключать порядок байтов.
В этом пространстве все наши архитектуры делятся на два класса:а к какому из этих классов относится архитектура, у которой нет регистров больше байта?
BIg и Little Endian.
или архитектура, у которой все регистры и адресуемые за команду ячейки памяти одинаковы и не делятся на байты, а делятся, например на 16-битные или 32-битные блоки?
или архитектура, которая может переключать порядок байтов в процессе работы?
или PDP10, у которой порядок байтов не big endian и не little endian?
Ясно теперь тебе, что значит "Биг Эндиан Архитектруа"?

что же я без тебя делал бы

так бы наверно и помер не просвещенный
void convert(char* source, int* dest, int int_count)
{
const int char_sz = sizeof(char) * 8;
const int mult = sizeof(int)/sizeof(char);
unsigned int *dst = dest;
unsigned char *src = source;
int i;
for(;int_count > 0; int_count--, dst++)
{
*dst = 0;
#ifdef little_endian
for(i = mult - 1; i >= 0; i--, src++)
(*dst) += (*src) << (i * char_sz);
#else
for(i = 0; i < mult; i++, src++)
(*dst) += (*src) << (i * char_sz);
#endif
}
}
Может я чего напортачил с утра, но должно быть примерно так. Остальное вроде проблемы компилятора. Я, разумется, предполагаю, что у нас числа не хранятся извратно.
Только что нашёл баг.




#define NUM_BITS 8
unsigned int _convert(const unsigned char* source, size_t _size)
{
assert(sizeof(unsigned) >= _size);
unsigned res = 0;
for(size_t i = 0; i < _size; ++i)
{
res |= source[i] << i * NUM_BITS;
}
return res;
}
> все широко используемые архитекруры для нас неразличимы
Я тебе ещё раз повторю: на большинстве архитектур
ты не считаешь невыравненные данные за одну команду.
Это будет не то же самое, что на x86: оно будет не просто медленее, оно не будет никак.
Поэтому не работает решение с ntoh*.
А представить вакуумированную сферическую лошадь я могу --- воображение позволяет.
---
...Я работаю антинаучным аферистом...
> или архитектура, у которой все регистры и адресуемые за команду ячейки памяти одинаковы
> и не делятся на байты, а делятся, например на 16-битные или 32-битные блоки?
Мне было бы интереснее узнать про архитектуры без (адресуемых) регистров
и с 18- и 21-разрядными ячейками оперативной памяти.
Реальные лошади в действии.
---
...Я работаю антинаучным аферистом...
А чем тебе не подходит идея создания union из 4-х char-ов и одного int-а?
Это суровая необходимость жизни.
Когда увидишь код, который на MC68EZ328 собирает big-endian число по октетам, поймёшь.
Если не поймёшь сразу, поймёшь потом, когда более простой код грохнется.
Как ни странно, я понял сразу, где засада.
---
...Я работаю антинаучным аферистом...
Тут вообще-то тоже кроется проблема порядка байтов.
в общем, я почитал трэд, и не могу понять чем автора не устраивает решение
union {
char chars[4];
int number;
} test;
А дальше если надо поменять порядок, то делать это в number-е, забыв про всякие свдиги и умножения.
А дальше если надо поменять порядок, то делать это в number-е, забыв про всякие свдиги и умножения.расскажи, как ты на BE машине это сделаешь без сдвигов и умножений?
SIGBUS тоже.
---
...Я работаю антинаучным аферистом...
в общем, я почитал трэд, и не могу понять чем автора не устраивает решениеДа я сам почитал тред и охренел

Меня и мою архитектуру вполне устроило первое решение.

htonl никто еще не отменял.не везде обращает порядок байтов

были взяты с NetBSD - должны быть и там.
всякая LE\BE фигня есть в glib.
поскольку "char" не обязан выравниваться на границу слова.
Наверное, на границу слова должно выравниваться предложенное "union",
пожалуй, тогда можно будет им воспользоваться, но только
им надо уметь правильно пользоваться.
---
...Я работаю антинаучным аферистом...
P.S. Про то, что "long" бывает подлиннее "4 chars", опять забыли.
Может быть и должны, но где и под какими именами?
---
...Я работаю антинаучным аферистом...
Лучшее - враг хорошего.

Это малоинтересно.
> А мы тут продолжаем дальше спорить и красоваться
Тебе это не нравится?
---
...Я работаю антинаучным аферистом...
htonl никто еще не отменял.Это было бы замечательное решение, но оно некорректно с точки зрения стандарта, ибо по стандарту содержимое union предсказуемо только пока используется одно из его полей, т.е. когда что-то определенное присвоено chars[], содержимое number непредсказуемо, например неизвестно где будут chars[4]: в начале number или в конце (если number больше chars[4] и вообще оптимизатор имеет право держать chars и number раздельно на каких-то участках кода.
в общем, я почитал трэд, и не могу понять чем автора не устраивает решение
union {
char chars[4];
int number;
} test;
А дальше если надо поменять порядок, то делать это в number-е, забыв про всякие свдиги и умножения.
Самое корректное решение, какое приходит в голову:
#include <limits.h> /* for CHAR_BIT */
#include <stdint.h> /* for uintmax_t */
int f(void)
{
unsigned char c[4]= {...};
#if ( UINTMAX_MAX >> CHAR_BIT*3 ) >= UCHAR_MAX
uintmax_t num = c[3] | ( (uintmax_t)c[2] << CHAR_BIT ) |
( (uintmax_t)c[1] << CHAR_BIT*2 ) | ( (uintmax_t)c[0] << CHAR_BIT*3 );
#else
# error "4-chars number will not fit in the widest integer type"
#endif
....................
}
для C90 удаляем:
#include <stdint.h>
и uintmax_t и UINTMAX_MAX заменяем на unsigned long и ULONG_MAX соответственно
Чем вас не устраивает моё решение, уважаемые архитектурные эксперты?

Кстати говоря, ещё можно заменить дефайны на проверку порядка каким-нить способом. Это возможно, но, имхо, не сильно необходимо.
> А мы тут продолжаем дальше спорить и красоватьсяАхтунг!
Тебе это не нравится?
Чем вас не устраивает моё решение, уважаемые архитектурные эксперты?Ну так оно неправильное, говорю те, что вот эта супер программа (она без умножений)
#include <assert.h>
#include <limits.h>
#include <stdio.h>
/*!
** \param source Указатель на кусок памяти где хранятся байты в порядке от старшего в младшему
** \param _size размер куска памяти в байтах
** \return Число, которое образуют эти байты
*/
unsigned int _convert(const unsigned char* source, size_t _size)
{
assert(sizeof(unsigned int) >= _size);
unsigned int res = 0;
for(size_t i = 0; i < _size; ++i)
{
res <<= CHAR_BIT;
res |= source[i];
}
return res;
}
int main
{
const unsigned char a[] = {0x3F, 0x34, 0x54, 0x00};
printf("%x\n", _convert(a, sizeof(a)/sizeof(a[0];
return 0;
}
будет всегда работать правильно, хоть на биг, хоть на смол, на какой хочешь архитектуре она тебе напечатает "3f345400"
:)
Оставить комментарий
williamsmith61
Ступор.Есть char* допустим с таким бинарным содержимым: 0x3F 0x34 0x54 0x00.
Как преобразовать это дело в int чтобы получить 0x3F345400?