fork download
  1. // Trying an obsolete GNU printf extension.
  2.  
  3. #include <limits.h>
  4. #include <stdio.h>
  5. #include <printf.h>
  6.  
  7. #define BITS(x) (sizeof(x) * CHAR_BIT)
  8.  
  9. #define MIN(a, b) \
  10. ({ __auto_type _x = (a); __auto_type _y = (b); \
  11.   (_y < _x) ? _y : _x; })
  12.  
  13. #define MAX(a, b) \
  14. ({ __auto_type _x = (a); __auto_type _y = (b); \
  15.   (_y > _x) ? _y : _x; })
  16.  
  17. int fillc(int c, int n, FILE *stream)
  18. {
  19. int result = 0;
  20. for (int i = 0; i < n && result != EOF; i++)
  21. result = fputc(c, stream);
  22. return result;
  23. }
  24.  
  25. int bitlimit(const struct printf_info *info)
  26. {
  27. if (info->is_char)
  28. return BITS(char);
  29. if (info->is_short)
  30. return BITS(short);
  31. if (info->is_long)
  32. return BITS(long int);
  33. if (info->is_long_double)
  34. return BITS(long long int);
  35. return BITS(int);
  36. }
  37.  
  38. int bitlength(unsigned long long int x)
  39. {
  40. return BITS(x) - __builtin_clzll(x | 1);
  41. }
  42.  
  43. int print_binary(FILE *stream, const struct printf_info *info, const void *const *args)
  44. {
  45. unsigned long long int value = *(const unsigned long long int *) args[0];
  46. int width = info->width;
  47. int count = MIN(bitlength(value), bitlimit(info));
  48.  
  49. if (!info->left)
  50. fillc(info->pad, width - count, stream);
  51. for (int i = count-1; i >= 0; i--)
  52. fputc(((value >> i) & 1) + '0', stream);
  53. if (info->left)
  54. fillc(info->pad, width - count, stream);
  55. return MAX(width, count);
  56. }
  57.  
  58. int print_binary_arginfo(const struct printf_info *info, size_t n, int *argtypes)
  59. {
  60. if (n > 0)
  61. argtypes[0] = PA_INT | PA_FLAG_LONG_LONG;
  62. return 1;
  63. }
  64.  
  65. int main(void)
  66. {
  67. register_printf_function('B', print_binary, print_binary_arginfo);
  68. for (int i = 0; i < 16; i++) {
  69. printf("<%8B>; <%-8B>; <%08B>; <%B>\n", i, i, i, i);
  70. }
  71. const char *format[] = {
  72. "<%hhB>\n", "<%hB>\n", "<%B>\n", "<%lB>\n", "<%llB>\n", 0};
  73. for (const char **p = format; *p != 0; p++) {
  74. printf(*p, -1ULL);
  75. }
  76. return 0;
  77. }
Success #stdin #stdout 0.01s 5284KB
stdin
Standard input is empty
stdout
<       0>; <0       >; <00000000>; <0>
<       1>; <1       >; <00000001>; <1>
<      10>; <10      >; <00000010>; <10>
<      11>; <11      >; <00000011>; <11>
<     100>; <100     >; <00000100>; <100>
<     101>; <101     >; <00000101>; <101>
<     110>; <110     >; <00000110>; <110>
<     111>; <111     >; <00000111>; <111>
<    1000>; <1000    >; <00001000>; <1000>
<    1001>; <1001    >; <00001001>; <1001>
<    1010>; <1010    >; <00001010>; <1010>
<    1011>; <1011    >; <00001011>; <1011>
<    1100>; <1100    >; <00001100>; <1100>
<    1101>; <1101    >; <00001101>; <1101>
<    1110>; <1110    >; <00001110>; <1110>
<    1111>; <1111    >; <00001111>; <1111>
<11111111>
<1111111111111111>
<11111111111111111111111111111111>
<1111111111111111111111111111111111111111111111111111111111111111>
<1111111111111111111111111111111111111111111111111111111111111111>