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


Автор: leniviy 1.3.2011, 13:48
Пример:
Код

typedef char int56[7];

Как получить указатель на старший байт, и дойти до младшего? Порядок байтов зависит от платформы.

Код

#include <stdio.h>

typedef union {
    int i;

    unsigned char uchars[4];

} testunion;


int main() {
  testunion un;
  un.i = 0x01234567;
  printf("%d (0x%08x)\n", (int)un.i, (int)un.i);
  printf("%02hx %02hx %02hx %02hx\n", (short)un.uchars[0], (short)un.uchars[1], (short)un.uchars[2], (short)un.uchars[3]);
  fflush(stdout);
  return 0;
}

x86
Код

19088743 (0x01234567)
67 45 23 01

sparc:
Код

19088743 (0x01234567)
01 23 45 67


Автор: xvr 1.3.2011, 14:21
Функции htonl и ntohl - преводят данные в фиксированный byte order


Автор: leniviy 1.3.2011, 14:36
Круто, но они не помогут с большими числами

Вот, написал такую конструкцию. На одних системах _endian.c будет 1, на других -1
Код

static const union {
  int i;
  char c;
} _endian = { (0xFF << ((sizeof(int)-1)*8)) | 0x01 };

Жаль, хотел на чистых макросах, без переменных.

Автор: xvr 1.3.2011, 14:45
Цитата(leniviy @ 1.3.2011,  14:36)
Круто, но они не помогут с большими числами

'Большие' - это сколько? Если 64 бита, то не помогут, увы  smile Если больше, то это уже массив слов в памяти, а он обычно на всех платформах располагается от младших адресов к старшим.

Можно проверить порядок байтов в run-time и перевернуть. Но это накладные расходы  smile 

Автор: mes 1.3.2011, 14:47
Цитата(xvr @  1.3.2011,  13:45 Найти цитируемый пост)
Можно проверить порядок байтов в run-time

а зачем проверять рантайм? когда и так известно будет на какую целевую платформу компилируют ?

Автор: leniviy 1.3.2011, 14:51
Цитата(mes @  1.3.2011,  14:47 Найти цитируемый пост)

а зачем проверять рантайм? когда и так известно будет на какую целевую платформу компилируют ?

Где известно? Есть стандартный макрос, у которого может быть 2 значения, типа 0 BE/1 LE? 

Автор: mes 1.3.2011, 15:20
у gcc вроде есть такой макрос.. что то типа __LITTLE_ENDIAN__

а что мешает вручную задавать этот макрос в зависимости от платформы под которую компилите ?

Автор: leniviy 1.3.2011, 17:37
Тогда уж надо полноценный ./configure скрипт использовать. Остановился на своём способе, вопрос решен.
Код

static const union {
  int i;
  char c;
} _endian = { (0xFF << ((sizeof(int)-1)*8)) | 0x01 };

#define BYTEOFFS(nbyte, size) (_endian.c == 1 ? (nbyte) : ( (size) - 1 - (nbyte)))
#define BYTEPTR(ptr, nbyte, size) (((char*)(ptr)) + BYTEOFFS(nbyte, size))

#define BYTERANGEOFFS(startbyte, endbyte, size) (_endian.c == 1 ? (startbyte) : ( (size) - 1 - (endbyte)))
#define BYTERANGEPTR(ptr, startbyte, endbyte, size) (((char*)(ptr)) + BYTERANGEOFFS(startbyte, endbyte, size))

#define NEXTBYTEPTR(ptr) (((char*)(ptr)) + _endian.c)
#define PREVBYTEPTR(ptr) (((char*)(ptr)) - _endian.c)



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