【发布时间】:2014-07-24 10:55:18
【问题描述】:
我遇到了一个问题,当在单个 printf 中多次调用时,返回字符串的函数返回不正确的值。起初我认为这是由于 binstr 的静态指定阻止了变量更新。在查看How to reset static variables within a function 之后,我认为这并不能解释这种行为。在创建函数时,我的目标是避免使用全局变量并避免在函数内动态分配并将 free() 内存的责任移交给调用例程。下面首先列出原始函数binstr_8。出于某种原因,我试图了解它是否在 printf 内被多次调用,它总是返回第一次返回的值 - 但在所有其他情况下表现如所期望(当未在同一个 printf 中多次调用时)
/* binstr_8 - binary string for uint8_t (char) */
char *
binstr_8 (uint8_t x)
{
static char binstr [sizeof(uint8_t) * CHAR_BIT + 1] = {0};
size_t szstr = sizeof (uint8_t) * CHAR_BIT;
size_t z = 0;
for (z = 0; z < szstr; z++)
binstr [szstr - 1 - z] = ((x >> z) & 0x1) ? '1' : '0';
return binstr;
}
一个简短的例子有助于解释:
printf ("\nTesting binstr_8 & binstr_8_dyn\n\n");
be = 0b01011000; // 88
printf (" 88 & 87 = %d (%s)\n\n", (88 & 87), binstr_8 (88 & 87));
printf (" %d %s rightmost bit off: %s\n\n", be, binstr_8 (be), binstr_8 (be & (be - 1)));
printf (" 88 %s\n 87 %s\n & ---------\n %s\n\n",
binstr_8 (88), binstr_8 (87), binstr_8 (88 & 87));
您可以下载示例程序的源代码binstr_8_test.cprintf语句的输出是:
Testing binstr_8 & binstr_8_dyn
88 & 87 = 80 (01010000)
88 01011000 rightmost bit off: 01011000
88 01011000
87 01011000
& ---------
01011000
当在printf 行中以“最右边位关闭”调用时,binstr_8 的每个实例都返回相同的值:01011000(仅为 88,与第一次调用 @ 时返回的相同987654333@ 语句中) 实际上,当binstr_8 在printf 中出现多次时,每次调用都返回88? (我什至对这些值进行了硬编码)那里发生了什么?
分解语句,使每个printf 只包含一个对binstr_8 的调用有效:
printf (" %d %s rightmost bit off: ", be, binstr_8 (be));
printf ("%s\n\n", binstr_8 (be & (be - 1)));
printf (" 88 %s\n", binstr_8 (88));
printf (" 87 %s\n", binstr_8 (87));
printf (" & ---------\n %s\n\n", binstr_8 (88 & 87));
输出:
88 01011000 rightmost bit off: 01010000
88 01011000
87 01010111
& ---------
01010000
我可以将函数重写为binstr_8_dyn 以动态分配char *binstr,然后使用包含对该函数的多次调用的相同printf 语句,它有效。 这怎么可能?示例:
/* same function re-written to dynamically allocate binstr */
char *
binstr_8_dyn (uint8_t x)
{
char *binstr = NULL;
size_t z;
size_t szstr = sizeof (uint8_t) * CHAR_BIT;
binstr = (char *)malloc (szstr + 1);
binstr [szstr] = '\0';
for (z = 0; z < szstr; z++)
binstr [szstr - 1 - z] = ((x >> z) & 0x1) ? '1' : '0';
return binstr;
}
/* snip */
printf (" %d %s rightmost bit off: %s\n\n", be, binstr_8_dyn (be), binstr_8_dyn (be & (be - 1)));
printf (" 88 %s\n 87 %s\n & ---------\n %s\n\n",
binstr_8_dyn (88), binstr_8_dyn (87), binstr_8_dyn (88 & 87));
输出正确:
88 01011000 rightmost bit off: 01010000
88 01011000
87 01010111
& ---------
01010000
现在我完全弄糊涂了,为什么不能在同一个 printf 中多次调用 binstr_8 而 binstr_8_dyn 可以。我忽略了什么基本原则?另外,除了使用静态或动态分配之外,我如何在不涉及全局或传递指针的情况下提供返回?
【问题讨论】:
-
printf (... binstr_8 (be), binstr_8 (be & (be - 1)));失败。binstr_8()被多次调用并更改其静态缓冲区中的数据之前printf()被调用。将printf()分解成更小的部分。 -
只是为了澄清:请不要在生产代码中使用
binstr_8_dyn()- 我会泄漏内存。每次通话都会有一点,但总而言之。 -
是的,我知道。我的目标是避免将 free() 的负担放在调用者身上,这也是最初决定在 binstr_8 中使用静态类型的原因。基本上,我为我的二进制库保留了两个原型。 binstr_8 用于一般用途,指向公共缓冲区的返回不是问题,而 binstr_8_dyn 用于有限用途。是的,我知道这两个问题都可以通过传递一个存储返回的指针来解决,但这是我试图避免的其他事情,以防止在 printf ("%s\n", binstr_8 (var)) 情况下令人沮丧的使用。 (这里所有的解决方案都很丑:)