C 如何将复合文字用于`fprintf()`具有任意基数的多个格式化数字?

C 如何将复合文字用于`fprintf()`具有任意基数的多个格式化数字?,c,c99,literals,compound-literals,C,C99,Literals,Compound Literals,我想将多个数字转换成某种表示形式,然后使用*printf()说明符的标志、宽度和精度。首选是避免全局或静态缓冲区。关键问题似乎是如何为每个转换后的数字提供char[] fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...); 如何使用C11复合文字来解决此问题? 如何使用C99(或更高版本)复合文字来解决此问题 C99 C11引入了复合文本,它不仅允许复杂的初始化结构,而且还允许“串联”变量 代码

我想将多个数字转换成某种表示形式,然后使用
*printf()
说明符的标志、宽度和精度。首选是避免全局或
静态
缓冲区。关键问题似乎是如何为每个转换后的数字提供
char[]

fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...);
如何使用C11复合文字来解决此问题?
如何使用C99(或更高版本)复合文字来解决此问题

C99 C11引入了复合文本,它不仅允许复杂的初始化结构,而且还允许“串联”变量

代码可以调用一个转换函数,并在每次函数调用时传入一个新的缓冲区(char[UTOA_BASE_N]){0},从而允许函数返回该缓冲区,该缓冲区现在根据需要编写,但仍在其生存期内。然后使用
“%s”
说明符可用的各种标志、宽度和精度打印返回的字符串

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

// Maximum buffer size needed
#define UTOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)

char *utoa_base(char *s, unsigned x, unsigned base) {
  s += UTOA_BASE_N - 1;
  *s = '\0';
  if (base >= 2 && base <= 36) {
    do {
      *(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[x % base];
      x /= base;
    } while (x);
  }
  return s;
}

#define TO_BASE(x,b) utoa_base((char [UTOA_BASE_N]){0} , (x), (b))

void test(unsigned x) {
  printf("base10:%10u base2:%5s  base36:%s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
  printf("%lu\n", strtoul(TO_BASE(x, 36), NULL, 36));
}

int main(void) {
  test(0);
  test(25);
  test(UINT_MAX);
}
Ref:有许多答案,但没有一个答案允许进行上述简单的内存管理(无
静态
),并访问
fprintf()
标记宽度、精度和使用数字的全部范围


这是一个答案。

注意:我断言返回值仍然在范围内,因为“……它的生命周期从进入与其关联的块开始,一直到该块的执行以任何方式结束。(输入封闭块或调用函数将暂停但不结束当前块的执行)。”C11dr§6.2.46@chux当前位置我认为你是对的,但是范围和寿命是不同的概念。一个对象有一个生命周期;标识符有一个作用域。与生命周期不同,作用域可以是不连续的。是的,是的,是的,这个答案('的例子)说明了为什么我们应该喜欢复合文字!;-)@这是故意的。复合文本没有“临时生存期”。6.2.4/8是指由函数的值返回的结构(例如,
foo().x=5;
)@m.m.:是的,chux关于复合文本是左值的有用观察,我发现了这一点。因此,非左值数组文字是不可能的,因为函数不能返回数组。(此外,复合文字不能是VLA,因此它们的生存期可以从块的开头开始。)为什么只使用C11?它同样适用于C99,也可以用C99解决。你是说你想用
%s
而不是
%d
或其他什么?M.M使用
%s
%d
或其他什么。我不想扼杀新奇的想法。@alk Q&A根据您的正确观察进行了修改。
base10:         0 base2:    0  base36:0 0
base10:        25 base2:11001  base36:P 25
base10:4294967295 base2:11111111111111111111111111111111  base36:1Z141Z3 4294967295