如何将无符号字符数组解释为十六进制数组?

时间:2018-12-01 19:13:40

标签: c arrays char hex checksum

我有一个无符号字符数组,我想计算其CRC32校验和。

CRC32函数还需要一个无符号的char指针,但是,它将数组解释为ASCII数组。

这是CRC函数:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

unsigned int crc32(unsigned char *message) 
{
   int i, j;
   unsigned int byte, crc, mask;

   i = 0;
   crc = 0xFFFFFFFF;
   while (message[i] != 0) {
      byte = message[i];            // Get next byte.
      crc = crc ^ byte;
      for (j = 7; j >= 0; j--) {    // Do eight times.
         mask = -(crc & 1);
         crc = (crc >> 1) ^ (0xEDB88320 & mask);
      }
      i = i + 1;
   }
   return ~crc;
}

int main(int argc, char **argv)
{
    unsigned char *arr;
    if ((arr = malloc(64)) == NULL) {
        perror("Could not allocate memory");
        exit(EXIT_FAILURE);
    }
    char str[] = "47d46d17e759a1dec810758c08004510002127d90000401152e4c0a8b21fc0a8b2255b9b5b9c000db20caabbccddee00000000000000000000000000";
    memcpy(arr, str, strlen(str));
    // ...
    unsigned int crc = crc32(arr);
    printf("CRC: 0x%x\n", crc); // 0xB6BA014A instead of 0xBF6B57A2

    return 0;
}

现在,我想计算CRC32,但无符号字符数组必须解释为十六进制数组。

F.ex。,这是计算出的CRC的结果:
输入:
"47d46d17e759a1dec810758c08004510002127d90000401152e4c0a8b21fc0a8b2255b9b5b9c000db20caabbccddee00000000000000000000000000"

  • 作为ASCII:0xB6BA014A(这是我通常得到的,因为它被解释为ASCII)
  • 为十六进制:0xBF6B57A2(这是我想要的校验和)

1 个答案:

答案 0 :(得分:2)

  

如何将无符号char数组解释为十六进制数组?

  • 将字符串中的每对十六进制字符转换为一个字节值。下面的代码通过复合文字转换为3个字节的 string ,然后调用strtoul()

    //                    v----------------------------------v _compound literal_
    arr2[i / 2] = strtoul((char[3]) {str[i], str[i + 1], '\0'}, 0, 16);
    

    更高级的代码将测试是否存在非十六进制字符或长度为奇/零的意外情况。


需要更改CRC计算

  • 将CRC计算的长度更改为基于长度而不是字符串的长度。

    // unsigned int crc32(const char *)
    unsigned int crc32(const void *m, size_t len)
    

    尽管未在下面进行编码,但是当uint32_t不是32位时,可以考虑使用unsigned int中的crc32()而不是unsigned中的#include <stdlib.h> #include <stdio.h> #include <string.h> unsigned int crc32(const void *m, size_t len) { const unsigned char *message = m; size_t i; int j; unsigned int byte, crc, mask; i = 0; crc = 0xFFFFFFFF; //while (message[i] != 0) { while (i < len) { byte = message[i]; // Get next byte. crc = crc ^ byte; for (j = 7; j >= 0; j--) { // Do eight times. mask = -(crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } i = i + 1; } return ~crc; }


一起

int main() {
  char str[] =
      "47d46d17e759a1dec810758c08004510002127d90000401152e4c0a8b21fc0a8b2255b9b5b9c000db20caabbccddee00000000000000000000000000";
  size_t len = strlen(str);
  unsigned int crc = crc32(str, len);
  printf("CRC: 0x%X\n", crc); // 0xB6BA014A instead of 0xBF6B57A2

  size_t len2 = (len + 1) / 2;
  unsigned char arr2[len2];
  for (size_t i = 0; i < len; i += 2) {
    arr2[i / 2] = strtoul((char[3]) {str[i], str[i + 1], '\0'}, 0, 16);
  }
  crc = crc32(arr2, len2);
  printf("CRC: 0x%X\n", crc); // 0xB6BA014A instead of 0xBF6B57A2

  return 0;
}

样品用量

CRC: 0xB6BA014A
CRC: 0xBF6B57A2

输出

while (message[i] != 0) {

OP原始代码具有未定义的行为,因为它寻找带有memcpy(arr, str, strlen(str));空字符,但是{ "username" : "TestUsername", "email" : "TestUsername@outlook.com", "password" : "Password01", "group" : "partial-permission" } 无法提供一个空字符。