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


Автор: andrew_121 25.8.2008, 18:14
Дарова!
Вопрос:
Нужно в unsigned short поменять местами первый и второй байт.
Поделитесь кодом...плиз... smile 

Автор: Lazin 25.8.2008, 18:28
Код

unsigned short a = 0xffcc;
unsigned short tmp = a;
a = (a >> 8) & 0x00FF ;
a |= tmp << 8;

Автор: Alek86 25.8.2008, 18:33
не люблю сдвиги
писалось на коленке

Код

typedef unsigned short ushort;

ushort chenge_bytes(ushort var) {
 typedef unsigned char byte;
 byte first = var % 256;
 byte second = var / 256;
 return first*256 + second;
}


если критично по скорости, то скорее всего компилер оптимизнет как надо

ЗЫ. кстати, стандарт не говорит, что sizeof(unsigned short) == 2 smile

Автор: andrew_121 25.8.2008, 18:51
Цитата(Alek86 @  25.8.2008,  18:33 Найти цитируемый пост)
ЗЫ. кстати, стандарт не говорит, что sizeof(unsigned short) == 2

Гм... А что он говорит?

Автор: Alek86 25.8.2008, 19:03
он говорит

1. sizeof(char) == sizeof(unsigned char) == 1;
2. sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long);

стандарта, как всегда, под рукой нету smile

Добавлено через 52 секунды
кроме того он говорит, что размер wchar_t тоже не обязательно 2 (чем меня окончательно убил smile ) 

Автор: andrew_121 25.8.2008, 19:25
Alek86, Мдя... Вот тебе и стандарт... smile 

Автор: cutwater 25.8.2008, 19:30
Что есть нормально. Компиляторо и платформо зависимые размеры типов данных

Автор: ama_kid 25.8.2008, 20:14
ну и на всякий случай мой вариант - без использования других переменных:
Код
    unsigned short Source = 0xFF11;

    *(unsigned char *)(&Source) ^= *((unsigned char *)(&Source)+1);
    *((unsigned char *)(&Source)+1) ^= *(unsigned char *)(&Source);
    *(unsigned char *)(&Source) ^= *((unsigned char *)(&Source)+1);

Автор: Alek86 25.8.2008, 20:22
Цитата(cutwater @  25.8.2008,  19:30 Найти цитируемый пост)
Что есть нормально. Компиляторо и платформо зависимые размеры типов данных

ничего хорошего в этом не вижу
особенно про размер "юникодового чара"

Автор: Gwendolen 25.8.2008, 21:55
Можно определять размер типа...
Код

#include <iostream>
#include <iomanip>

template <class T_MY_INT>
T_MY_INT chenge_bytes(T_MY_INT var)
{
    const T_MY_INT shifts = sizeof(T_MY_INT) * 4;
    return (var >> shifts) | (var << shifts);
}

int main()
{
    char my_char = 0x56;
    std::cout << std::hex << my_char << "  " << chenge_bytes(my_char) << std::endl;

    unsigned short short_int = 0xffcc;
    std::cout << std::hex << short_int << "  " << chenge_bytes(short_int) << std::endl;


    unsigned my_int = 0xaabbccdd;
    std::cout << std::hex << my_int << "  " << chenge_bytes(my_int) << std::endl;

    unsigned long long int long_int = 0x8899aabbccddeeff;
    std::cout << std::hex << long_int << "  " << chenge_bytes(long_int) << std::endl;

    return 0;
}


Автор: Lazin 25.8.2008, 22:14
Цитата(Gwendolen @  25.8.2008,  21:55 Найти цитируемый пост)
return (var >> shifts) | (var << shifts);

мне кажется здесь может быть UB

Автор: andrew_121 25.8.2008, 22:23
Вопрос решен. Всем огромное спасибо!

Автор: bsa 25.8.2008, 22:37
Цитата(Lazin @ 25.8.2008,  22:14)
Цитата(Gwendolen @  25.8.2008,  21:55 Найти цитируемый пост)
return (var >> shifts) | (var << shifts);

мне кажется здесь может быть UB

Почему? Не вижу ни единой причины для этого.

Автор: mes 25.8.2008, 23:16
Цитата(Lazin @  25.8.2008,  22:14 Найти цитируемый пост)
Цитата(Gwendolen @  25.8.2008,  21:55 )
return (var >> shifts) | (var << shifts);


мне кажется здесь может быть UB 


для UB в подобном случае должно быть еше и присваивание,  для двух (и более) членов ссылаюшихся на одну и ту же область памяти..
в примере хоть и две var,  но они только отдают значение и присваивания для них нет...

Автор: W4FhLF 26.8.2008, 06:26
Ещё такой вариант: 

Код

unsigned short swap(unsigned short var)
{
    __asm mov ax,var
    __asm ror ax,8
}


Добавлено @ 06:28
Цитата(Gwendolen @  25.8.2008,  21:55 Найти цитируемый пост)
 return (var >> shifts) | (var << shifts);


Вот, кстати, реализация машинной команды ROR на С. 

Автор: ksili 26.8.2008, 11:28
W4FhLF, забыл ещё назад из AX в var выгрузить

Автор: W4FhLF 26.8.2008, 11:32
ksili, не забыл. Зачем? Возвращаемое значение в ax. Параметр не по ссылке передан. 

Автор: JackYF 26.8.2008, 12:15
Цитата(W4FhLF @  26.8.2008,  05:26 Найти цитируемый пост)
unsigned short swap(unsigned short var)
{
    __asm mov ax,var
    __asm ror ax,8
}

x86-only, intel assembler only...

Автор: W4FhLF 26.8.2008, 16:01
JackYF, и что? Я где-то утверждал обратное или навязывал этот способ? Автор топика где-то говорил под какую платформу пишет? Просто тут все(почти) привели платформозависимый код, но почему-то ты выделил именно мой smile 

Автор: JackYF 26.8.2008, 16:03
Цитата(W4FhLF @  26.8.2008,  15:01 Найти цитируемый пост)
Я где-то утверждал обратное или навязывал этот способ?

Это не наезд, это предупреждение тем, кому может понравится данный способ. Мы в общих вопросах, поэтому узкоспециализированные решения хорошо бы помечать сразу в постах как таковые.

Автор: W4FhLF 26.8.2008, 16:26
JackYF, согласен. Я, в общем-то, подозревал, что кто-то об этом упомянет. 

Автор: MAKCim 26.8.2008, 22:45
Цитата(JackYF @  26.8.2008,  12:15 Найти цитируемый пост)
x86-only

ну еще x86_64  smile 

Автор: W4FhLF 27.8.2008, 05:08
Цитата(MAKCim @  26.8.2008,  22:45 Найти цитируемый пост)
ну еще x86_64


Он, конечно, выполнится, только unsogned short там 4 байта smile 

Автор: bsa 27.8.2008, 10:50
Цитата(W4FhLF @ 27.8.2008,  05:08)
Цитата(MAKCim @  26.8.2008,  22:45 Найти цитируемый пост)
ну еще x86_64


Он, конечно, выполнится, только unsogned short там 4 байта smile

 smile 
Код
#include <iostream>

int main()
{
    std::cout << "C=" << sizeof(char) << std::endl;
    std::cout << "UC=" << sizeof(unsigned char) << std::endl;
    std::cout << "S=" << sizeof(short) << std::endl;
    std::cout << "US=" << sizeof(unsigned short) << std::endl;
    std::cout << "I=" << sizeof(int) << std::endl;
    std::cout << "UI=" << sizeof(unsigned int) << std::endl;
    std::cout << "L=" << sizeof(long) << std::endl;
    std::cout << "UL=" << sizeof(unsigned long) << std::endl;
    std::cout << "LL=" << sizeof(long long) << std::endl;
    std::cout << "ULL=" << sizeof(unsigned long long) << std::endl;
    return 0;
}
Код
$ ./test
C=1
UC=1
S=2
US=2
I=4
UI=4
L=8
UL=8
LL=8
ULL=8
$ uname -m
x86_64

Автор: MAKCim 27.8.2008, 10:50
Цитата(W4FhLF @  27.8.2008,  05:08 Найти цитируемый пост)
Он, конечно, выполнится, только unsogned short там 4 байта

нет
хотя это на усмотрение компилятора
в GCC 
sizeof(short) = 2
sizeof(int) = 4
sizeof(long) = 8

насколько я знаю в VS sizeof(int) = sizeof(long) = 4

Автор: W4FhLF 27.8.2008, 11:05
Ребята, вы правы, перепутал мну. 

Автор: andrew_121 27.8.2008, 12:44
Вопрос:
Чему должно равнятся 4096 после такой перестановки?

Автор: MAKCim 27.8.2008, 12:48
Цитата(andrew_121 @  27.8.2008,  12:44 Найти цитируемый пост)
Чему должно равнятся 4096 после такой перестановки?


00010000 00000000 -> 00000000 00010000 = 16

Автор: andrew_121 27.8.2008, 12:49
MAKCim, Спасибо! Я так и думал, просто решил перепроверится! Тебе плюсик!

Автор: Ln78 27.8.2008, 15:57
 smile 
Цитата(W4FhLF @  27.8.2008,  06:08 Найти цитируемый пост)
только unsogned short там 4 байта 

Цитата(W4FhLF @  27.8.2008,  12:05 Найти цитируемый пост)
Ребята, вы правы, перепутал мну.  

Ну вот, а я было подумал, что это новый тип такой, несогнутый (unsogned ), а потому и длинный smile 

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