简体   繁体   English

如何用根据类型确定的位数打印f(“%0x”)?

[英]How to printf(“%0x”) with the number of digits determined from the type?

I can specify the number of digits like printf("%08x", ...) . 我可以指定数字的数量,例如printf("%08x", ...) But I'd like to automatically adjust the number of digits according to the data type, (eg, long (64 bits) should automatically have 64/4=16 digits). 但是我想根据数据类型自动调整位数(例如, long (64位)应自动具有64/4 = 16位数字)。 Is there a way to do so? 有办法吗? Thanks. 谢谢。

How to printf(“%0x”) with the number of digits determined from the type? 如何用根据类型确定的位数打印printf(“%0x”)

1) Find the bit width 1)找到位宽

Use sizeof, CHAR_BIT to find the bit width sizeof(x)*CHAR_BIT 1 or see below alternative. 使用sizeof, CHAR_BIT查找位宽 sizeof(x)*CHAR_BIT 1或参见以下替代方法。

2) Find the nibble width 2)找到半字节宽度

(bit_width + 3)/4 for the nibble width - number of hexadecimal characters. (bit_width + 3)/4表示半字节宽度-十六进制字符数。

3) Pass the width 3)通过宽度

Use "*" to pass in the width and print using the widest type, uintmax_t . 使用"*"传递宽度并使用最宽的类型uintmax_t打印。

#include <float.h>
#include <limits.h>
#include <stdio.h>

#define PRINTF_XW(x) printf("%0*jx\n", (int)(sizeof(x)*CHAR_BIT+3)/4, (uintmax_t) (x))

int main(void) {
  unsigned char uc = 1;
  unsigned short us = 2;
  unsigned u = 3;
  unsigned long ul = 4;
  unsigned long long ull = 5;
  uintmax_t uj = 6;

  PRINTF_XW(uc);
  PRINTF_XW(us);
  PRINTF_XW(u);
  PRINTF_XW(ul);
  PRINTF_XW(ull);
  PRINTF_XW(uj);
  return 0;
}

Sample output, may differ amongst platforms. 示例输出在平台之间可能有所不同。

01
0002
00000003
0000000000000004
0000000000000005
0000000000000006

Alternative 替代

Another approach would use _Generic - tis a bit more work - and more rewards. 另一种方法是使用_Generic需要更多工作- _Generic更多回报。
See unsigned long long uf:42; 参见unsigned long long uf:42; example below. 下面的例子。

#include <float.h>
#include <limits.h>
#include <stdint.h>

int hexwidth(uintmax_t u) {
  int count = 3;
  while (u) {
    u >>= 1;
    count++;
  }
  return count/4;
}

// Default case useful for other unsigned types wider than `unsigned`
#define HEXWIDTH(s) _Generic((s), \
    unsigned char: hexwidth(UCHAR_MAX), \
    unsigned short: hexwidth(USHRT_MAX), \
    unsigned : hexwidth(UINT_MAX), \
    unsigned long: hexwidth(ULONG_MAX), \
    unsigned long long: hexwidth(ULLONG_MAX), \
    default: hexwidth((s)*0u - 1u) \
    )

#define PRINTF_XW(x) printf("%0*jx\n", HEXWIDTH(x), (uintmax_t) (x))

With language extensions that allow wider than unsigned fields - works nicely too. 通过允许比unsigned字段更宽的语言扩展,也可以很好地工作。

int main(void) {
  struct {
      unsigned long long uf:42;
  } s1 = {7};
  struct {
      unsigned long long uf:51;
  } s2 = {8};

  PRINTF_XW(s1.uf);
  PRINTF_XW(s2.uf);
}

Output 产量

00000000007   <-- 11 digits
0000000000008 <-- 13 digits

Macro-magic could replace hexwidth(uintmax_t u) as follows with a compile time calculation: Macro-magic可以用编译时间计算如下替换hexwidth(uintmax_t u)

#define NW3(x) (((x) > 0xFu) ? 2 : 1)
#define NW4(x) (((x) > 0xFFu) ? NW3((x)>>8)+2 : NW3(x))
#define NW5(x) (((x) > 0xFFFFu) ? NW4((x)>>16)+4 : NW4(x))
#define NW6(x) (((x) > 0xFFFFFFFFu) ? NW5((x)>>32)+8 : NW5(x))
#define NW(x) (((x) > 0xFFFFFFFFFFFFFFFFu) ? NW6((((x)+0llu)>>32)>>32)+16 : NW6((x)+0llu))

// Default case useful for all unsigned types as wide/wider than `unsigned`
#define HEXWIDTH(s) _Generic((s), \
    unsigned char: NW(UCHAR_MAX), \
    unsigned short: NW(USHRT_MAX), \
    default: NW((s)*0u - 1u) \
    )

1 This works well when there is no padding in the type - common amongst standard unsigned integer types. 1当类型中没有填充时,这很好用-在标准无符号整数类型中很常见。

You should probably look into C's <inttypes.h> 您可能应该研究C的<inttypes.h>

#include <inttypes.h>

unit8_t value = 0x34;
printf("The value formatted for 8 bits is %" PRIx8 ".", value);

Note the PRIx8 is a string, which correctly will format for "printf" "hexadecimal" "eight bits". 请注意, PRIx8是一个字符串,正确地将其格式设置为“ printf”,“十六进制”,“八位”。

Note that the lack of commas between the strings are not a mistake. 请注意,字符串之间没有逗号不是错误。 This is a formatting technique that uses a feature in C called "automatic string concatenation", such that the three strings will get slapped together. 这是一种格式化技术,使用了C中称为“自动字符串连接”的功能,因此三个字符串将被拍打在一起。 The PRIx8 is just a convenience which means the correct formatting for an 8 bit hexadecimal value. PRIx8只是一种方便,这意味着对8位十六进制值进行正确的格式化。

To get the similar output formatted for 32 bits, you would use PRIx32 . 要获得格式化为32位的类似输出,可以使用PRIx32

For a brief overview of the inttypes.h output formats, you can look at Good introduction to <inttypes.h> 有关inttypes.h输出格式的简要概述,请参见<inttypes.h>的简介。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM