Обход структуры в сетевом порядке байтов (Big Endian) --- Язык C - PullRequest
1 голос
/ 28 мая 2011

У меня есть серия структур, хранящихся в сетевом порядке байтов. Я хочу получить их. Как я могу это сделать.

структуры этого типа хранятся в файле. Я хочу пройти через все эти структуры. Любая помощь с благодарностью.

Ответы [ 3 ]

0 голосов
/ 28 мая 2011

Если предположить, что значения int на самом деле имеют длину 4 байта, то вы можете использовать код, подобный следующему:

enum { STRUCT_SIZE = 8 };

void data_reader(FILE *fp)
{
    char buffer[STRUCT_SIZE];
    struct node data;

    while ((fread(buffer, sizeof(buffer), 1, fp) == 1)
    {
        unpack_struct(buffer, &data);
        ...stash the unpacked structure...
    }
}

void unpack_struct(const char buffer[STRUCT_SIZE], struct node *data)
{
    load_int4(&buffer[0], &data->data);
    load_int4(&buffer[4], &data->length);
}

void load_int4(const char *data, int *value)
{
    *value = ((((data[0] << 8 | data[1]) << 8) | data[2]) << 8) | data[3];
}

Существует более одного способа написания load_int4(), но это достаточно компактно и достаточно ясно для большинства целей. Его можно превратить в макрос или (лучше) в встроенную функцию.

Точно так же вы можете расширить это, чтобы охватить больше типов: load_int2(), load_int8(), возможно, беззнаковые альтернативы и т. Д. Вы можете подумать, является ли обычный int лучшим типом для использования в структуре; может быть лучше использовать типы из <stdint.h> или <inttypes.h>, такие как int32_t.

0 голосов
/ 28 мая 2011

Мне бы очень хотелось увидеть, что вы написали до сих пор. Но в то же время, я предполагаю, что вы можете конвертировать между порядком байтов (если вы этого не сделаете, Google может предоставить тонну учебников). Это оставляет вас с задачей чтения структуры из файла. Прямо сейчас мне не ясно, что length делает в вашей структуре. Сейчас кажется, что это просто обычные данные, поэтому для чтения структуры вы должны сделать что-то вроде следующего:

struct node 
{ 
  int data; 
  int length; 
};

FILE* pFile = fopen( "myfile.bin" , "rb" );
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

char* buffer = (char*) malloc(sizeof(struct node));
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

size_t result = fread(buffer, 1, sizeof(struct node), pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

// 1- perform the conversion from one endianness to another
// 2- convert from char* to node*
node* tmp_struct = (node*)buffer;

printf("data: %d\n", tmp_struct->data);
printf("length: %d\n", tmp_struct->length);

fclose (pFile);
free (buffer);

Этот код не был протестирован, но он иллюстрирует задачи приложения. Приведенный выше пример читает только первую доступную структуру в файле. Я оставлю все остальное как домашнее задание для вас.

0 голосов
/ 28 мая 2011

Для одного целого числа

Вы можете использовать следующую функцию смены порядкового номера: x - целое число, для которого вы хотите получить обратный порядковый номер, atomicity - атомарность порядкового номера, означает числобитов, которые рассматриваются как группа.Обычно это 8.

unsigned int toggle_endian (unsigned int x, int atomicity)
{
  unsigned int t = 0;
  unsigned int mask, sft_amt;

  switch (atomicity)
    {
    case 8:
      mask = 0xff;
      sft_amt = 8;
      break;

    case 16:
      mask = 0xffff;
      sft_amt = 16;
      break;

    default:
      /* Invalid atomicity value, return 0x0 */
      return 0x0;
    }

  while (x)
    {
      t <<= sft_amt;
      t |= (x & mask);
      x >>= sft_amt;
    }
  return t;
}

Также посмотрите: http://en.wikipedia.org/wiki/Endianness

РЕДАКТИРОВАТЬ1:

Для структурных / составных данных

Для структуры или некоторого типа динамического размера, который необходимо преобразовать в обратный порядок байтов, может помочь следующая функция:

your_type conv_endian (your_type x)
{
  your_type y;
  char *arr = (char *) &x;
  char *arr_conv = (char *) &y;
  int n, i, j;

  n = sizeof (your_type);

  for (i=n-1, j=0; i>=0; i--, j++)
  {
    arr_conv[j] = arr[i];
  }
  return y;
}

Проверьте вышеуказанную функцию с помощью приведенного ниже драйвера:

typedef struct _your_type {
  unsigned int a, b;
} your_type;

test conv_endian (your_type x);
int main (void)
{
  your_type x, y;
  x.a = 0x12ab34cd;
  x.b = 0x98ef76af;
  y = conv_endian (x);
  printf ("\n%x %x", x.a, x.b);
  printf ("\n%x %x", y.a, y.b);
  printf ("\n");
  return 0;
}

РЕДАКТИРОВАТЬ 2:

Для любой структуры

/* x: base address of the memory
 * n: length of the memory
 */
void reverse_endian (void *x, int n)
{
  char *arr_conv, *arr, t;

  arr = arr_conv = (char *) x;
  arr += (n-1);

  n/=2;

  while (n)
  {
    t = *arr_conv;
    *arr_conv = *arr;
    *arr = t;

    n--;
    arr_conv++;
    arr--;
  }
}

Проверить этот пост Обмен endiannes в C

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...