【问题标题】:Considering only 4 bits at a time when converting decimal to hex将十进制转换为十六进制时一次只考虑 4 位
【发布时间】:2019-03-05 18:10:04
【问题描述】:

我有一个 C 函数可以将十进制转换为十六进制字符串 hexConversion:

int hexConversion(int num){
    char hex_buffer[9];
    unsigned int mask = 4026531840;
    for(int i = 0; i < 9; i++){
        int temp = mask & num;
        if(temp < 10){
            hex_buffer[i] = temp + '0';
        }
        else if(temp == 10){
            hex_buffer[i] = 'A';
        }
        else if(temp == 11){
            hex_buffer[i] = 'B';
        }
        else if(temp == 12){
            hex_buffer[i] = 'C';
        }
        else if(temp == 13){
            hex_buffer[i] = 'D';
        }
        else if(temp == 14){
            hex_buffer[i] = 'E';
        }
        else if(temp == 15){
            hex_buffer[i] = 'F';
        }
        mask >>= 4;
    }

    hex_buffer[8] = '\0';

    for(int i = 0; i < sizeof(hex_buffer); i++){
        printf("%c", hex_buffer[i]);
    }
}

带驱动代码:

int main(){
    hexConversion(2);
    hexConversion(255);
    hexConversion(-1);
    hexConversion(INT_MAX);
    hexConversion(INT_MIN);
    hexConversion(0xDEADBEEF);
}

我的输出是: 00000002 0000000F 0000000F 0000000F 00000000 0000000F

每个输出的最后一个值都是正确的,但最后一个值之前的所有值都没有计算。我相信这是因为我的 temp = mask &amp; num 没有产生不是 0-15 的值。我的问题是,我如何一次只考虑 4 位,以便我的所有 temp 值都在这个范围内?

【问题讨论】:

  • 你应该转移num而不是maskmask 应该掩盖下半字节。请注意,您最好使用无符号类型。
  • 最简单的事情可能是从右到左生成字符串。检查num &amp; 0x0f 并转移号码
  • 这里不涉及小数。您将二进制值编码为十六进制字符串。为了使十进制有意义,您需要转换十进制字符串,或者使用在内部将数字表示为十进制的计算机。
  • 请注意,循环将写入hex_buffer[8],稍后将被hex_buffer[8] = '\0';覆盖
  • @WeatherVane 这个错误当然不是hex_buffer[8] = '\0' 而是转9次(还有其他几个错误)

标签: c function binary hex output


【解决方案1】:

在不考虑问题的情况下查看您的代码的第一句话是,为什么您可以很好地管理案例 0..9,但您将案例 A 和 B ... 和 F 分开,而不是像您为数字?

所以

int hexConversion(int num){
  char hex_buffer[9];
  unsigned int mask = 4026531840;
  for(int i = 0; i < 9; i++){
    int temp = mask & num;
    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else if (temp < 16) {
      hex_buffer[i] = temp - 10 + 'A';
    }
    else {
      hex_buffer[i] = '?';
    }
    mask >>= 4;
  }

  hex_buffer[8] = '\0';

  for(int i = 0; i < sizeof(hex_buffer); i++){
    printf("%c", hex_buffer[i]);
  }
}

如果代码是正确的,我添加了测试if (temp &lt; 16) 通常没用,但结果是:

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra h.c
h.c: In function ‘hexConversion’:
h.c:23:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0; i < sizeof(hex_buffer); i++){
                      ^
pi@raspberrypi:/tmp $ ./a.out
00000002000000?F0??????F???????F000000000??????F

所以在您的解决方案中,由于代码中的错误,您不会写一些索引

一种方法是:

void hexConversion(int num){
  char hex_buffer[9];

  for(size_t i = 0; i < sizeof(hex_buffer) -1; i++){
    int temp = (num >> (28-4*i)) & 0xf;
    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else {
      hex_buffer[i] = temp - 10 + 'A';
    }
  }
  hex_buffer[8] = 0;
  puts(hex_buffer);
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra h.c
pi@raspberrypi:/tmp $ ./a.out
00000002
000000FF
FFFFFFFF
7FFFFFFF
80000000
DEADBEEF

注意您的代码假设 int 在 32b 上,与大小无关(但假设 char 是 8 位):

void hexConversion(int num){
  char hex_buffer[sizeof(int)*2 + 1];

  for(size_t i = 0; i < sizeof(int)*2; i++){
    int temp = (num >> (sizeof(int)*8-4-4*i)) & 0xf;

    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else {
      hex_buffer[i] = temp - 10 + 'A';
    }
  }
  hex_buffer[sizeof(int)*2] = 0;
  puts(hex_buffer);
}

【讨论】:

    【解决方案2】:

    这取决于你的系统,但如果你想从你的价值中提取 nybbles 您最终可以在您的值上应用 0xF (masks >> (4 * n)) 例如 如果我得到一个看起来像这样的二进制数据0x4602 = 0100 0110 0000 0010 我只需要提取这个的第一部分 我可以在这个 0x4602 上使用带有 & 掩码的 0xF000 = 1111 0000 0000 0000 得到这个值的第一部分 这会给我们 0xF000 = 1111 0000 0000 0000 &0x4602 = 0100 0110 0000 0010 result would be 0x4000 = 0100 0000 0000 0000

    要获得此值的第 n 部分,您可以将 (0xF000) 漂移 >> 4 n 次

    【讨论】:

      【解决方案3】:

      您需要从 0-7 运行循环,并在将掩码应用到下半字节后移动数字。

      for(int i = 0; i < 8; i++){
          int temp = (mask & num) >> (28 -4*i);
      

      【讨论】:

        猜你喜欢
        • 2022-01-13
        • 2017-03-08
        • 1970-01-01
        • 1970-01-01
        • 2011-07-28
        • 1970-01-01
        • 2016-10-14
        相关资源
        最近更新 更多