Обмен эндианнес в C - PullRequest
       4

Обмен эндианнес в C

1 голос
/ 04 июня 2011

У меня есть эта строка

c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000

Как ее поменять местами, чтобы она стала

000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1

Эти два в основном примеры, но это то, что мне нужно сделать, но незнаю как, поскольку я очень мало знаю о C.

Выше две строки на самом деле являются unsigned char [] в программе на C

PS Не думайте, что я не прошел через Google.Я сделал, но я нашел очень мало того, что мне нужно, поэтому каждая попытка сделать это потерпела неудачу.

Ответы [ 5 ]

6 голосов
/ 04 июня 2011
for (int i = 0; i < size; i += 2) {
    myNewStr[size - i - 2] = myStr[i];
    myNewStr[size - i - 1] = myStr[i + 1]; 
}
1 голос
/ 04 июня 2011

как то так;вероятно, не идеально, но дает вам идею.Вам понадобится соответствующая проверка ошибок, инициализация вашего буфера и т. Д.

Редактировать: Я сделал предположение, которого не должно было быть, возможноЯ интерпретировал вашу строку как шестнадцатеричное представление байтов, поэтому я взял c1 как unsigned char и переключил ее, например, 00.Если ваша строка на самом деле строчная c, число 1 и т. Д., То ответ Мики - то, что вы хотите, а не мое.

void reverse_string(unsigned char *buf, int length)
{
    int i;
    unsigned char temp;

    for (i = 0; i < length / 2; i++)
    {
        temp = buf[i];
        buf[i] = buf[length - i - 1];
        buf[length - i - 1] = temp;
    }   
}
0 голосов
/ 04 июня 2011

Если у вас есть строка: "12ab\0", обратный порядковый номер этой строки будет "\0ba21".

Если у вас есть числовое значение: 0x12ab, обратный порядковый номер этого числового значения будет 0xab12.

Какой из них вы хотите.

Вот функция для преобразования между порядком байтов, которая будет обрабатывать переданный аргумент как блок памяти и изменять порядок байтов.

Код

#include <stdio.h>
typedef struct _test {
  unsigned int a, b;
} test;

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


int main (void)
{
  char str1[] = "c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000";
  char str2[] = "hellio";
  /* Assigns the str1 as hex values */
  unsigned char str3[] = {0xc1, 0xeb, 0x04, 0x4f, 0x07, 0x08, 0x01, 0x5b, 0x26, 0x79, 0x13, 0xfc, 0x4d, 0xff, 0x5a, 0xab, 0xe3, 0xdd, 0x4a, 0x97, 0xf1, 0x0f, 0x7b, 0xa9, 0x35, 0xcd, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00};
  test x;
  char q = 0x12;
  int v = 0x1234abcd;
  int i, n;

  x.a = 0x12ab34cd;
  x.b = 0x98ef76af;

  printf ("\nNormal : x.a = %x x.b = %x", x.a, x.b);
  reverse_endian (&x, sizeof (x));
  printf ("\nReverse: x.a = %x x.b = %x", x.a, x.b);

  printf ("\nNormal : q = %x", q);
  reverse_endian (&q, sizeof (q));
  printf ("\nReverse: q = %x", q);

  printf ("\nNormal : q = %x", v);
  reverse_endian (&v, sizeof (v));
  printf ("\nReverse: q = %x", v);

  printf ("\nNormal : str1 = %s", str1);
/* minus 1 to avoid the trailing nul character */
  reverse_endian (str1, sizeof (str1) - 1);
  printf ("\nReverse: str1 = %s", str1);

  printf ("\nNormal : str2 = %s", str2);
/* minus 1 to avoid the trailing nul character */
  reverse_endian (str2, sizeof (str2) - 1);
  printf ("\nReverse: str2 = %s", str2);

  printf ("\nNormal : str3 = ");
  n = sizeof (str3);
  for (i=0; i < n; i++)
  {
    printf ("%x", (str3[i]>>4)&0x0f);
    printf ("%x", str3[i]&0x0f);
  }
  reverse_endian (str3, sizeof (str3));
  printf ("\nReversed: str3 = ");
  for (i=0; i < n; i++)
  {
    printf ("%x", (str3[i]>>4)&0x0f);
    printf ("%x", str3[i]&0x0f);
  }

  printf ("\n");
  return 0;
}

Вывод

Normal : x.a = 12ab34cd x.b = 98ef76af
Reverse: x.a = af76ef98 x.b = cd34ab12
Normal : q = 12
Reverse: q = 12
Normal : q = 1234abcd
Reverse: q = cdab3412
Normal : str1 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reverse: str1 = 000000000063dc539ab7f01f79a4dd3ebaa5ffd4cf319762b5108070f440be1c
Normal : str2 = hellio
Reverse: str2 = oilleh
Normal : str3 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reversed: str3 = 000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1

Обратите внимание, что строки str1, str2 просто перевернуты, поскольку каждый символ строки составляет один байт.Та же строка символов, которую вы указали, представлена ​​в виде байтовой строки в str3.Его шестнадцатеричные значения показаны как выходные данные.Операции для всех данных идентичны, поскольку они касаются только порядка следования байтов в памяти.

0 голосов
/ 04 июня 2011

Небольшая альтернатива ответу Мики. Я предполагаю, что размер предварительно рассчитан и четен, и проверяю, что он больше 0, потому что s-2 потенциально UB Я изменяю строку на месте только для разнообразия.

static inline void swap_uchar(unsigned char *l, unsigned char *r) {
    unsigned char tmp = *l;
    *l = *r;
    *r = tmp;
}

void reverse_pairs(unsigned char *s, size_t size) {
    if (size > 0) {
        for (unsigned char *l=s, *r=s+size-2; l < r; l += 2, r -= 2) {
            swap_uchar(l, r);
            swap_uchar(l+1, r+1);
        }
    }
}
0 голосов
/ 04 июня 2011

Это похоже на то, что вы хотите, включая как минимум string.h и stdlib.h.

unsigned char *stringrev(const unsigned char *s) {
  size_t n = strlen((const char *)s);
  unsigned char *r = malloc(n + 1);

  if (r != NULL && !(n & 1)) {
    const unsigned char *fp = s;
    unsigned char *rp = r + n;

    for(*rp = '\0'; n > 1; n -= 2) {
        *--rp = fp[1];
        *--rp = fp[0];
        fp += 2;
    }
  }
  return r;
}
...