以网络字节顺序遍历struct(Big Endian)--- C语言

时间:2011-05-28 05:04:33

标签: c

我有一系列以网络字节顺序存储的结构。我想要检索它们。我怎么能这样做。

此类型的结构存储在文件中。我想遍历所有这些结构。 非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

对于单个整数

您可以使用以下字节序更改函数: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

<强> EDIT1:

对于结构/合成数据

对于需要转换为反向字节的结构或某种类型的动态大小,以下函数会有所帮助:

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;
}

<强> EDIT2:

对于任何结构

/* 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--;
  }
}

查看此帖子Swapping endiannes in C

答案 1 :(得分:0)

假设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

答案 2 :(得分:0)

我真的很想看到你到目前为止所写的内容。但与此同时,我假设您可以在字节序之间进行转换(如果不这样,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);

此代码尚未经过测试,但它说明了应用程序的任务。上面的示例仅读取文件中的第一个可用结构。我会把剩下的作为你的功课。