[英]Why does function return only one value when called multiple times in a single printf?
I ran across an issue where a function that returns a character string returns incorrect values when called multiple times within a single printf . 我遇到了一个问题,即在单个printf中多次调用返回字符串的函数时,返回错误值。 At first I thought it was due to the static designation of binstr preventing the variable from updating.
起初,我认为这是由于binstr的静态名称阻止了变量的更新。 After reviewing How to reset static variables within a function I don't think that explains the behavior.
在回顾了如何在函数中重置静态变量之后,我认为这不能解释其行为。 In creating the function, my goal was to avoid global variables and to avoid dynamically allocating within the function and turning over the responsibility to free() the memory to the calling routine.
在创建函数时,我的目标是避免全局变量,并避免在函数内动态分配,并将free()内存的职责移交给调用例程。 Below the original function
binstr_8
is listed first. 首先列出了原始功能
binstr_8
。 For reasons I'm trying to understand if it is called multiple times within printf
it always returns the value of the first return - but behaves as desired in all other situations (when not called multiple times in the same printf
) 出于某种原因,我试图了解它是否在
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;
}
A short example helps explain: 一个简短的示例有助于说明:
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));
You can download the source of the example program binstr_8_test.c The output from the printf
statements are: 您可以下载示例程序的源binstr_8_test.c从输出
printf
语句是:
Testing binstr_8 & binstr_8_dyn
88 & 87 = 80 (01010000)
88 01011000 rightmost bit off: 01011000
88 01011000
87 01011000
& ---------
01011000
When called in the printf
line with "rightmost bit off", each instance of binstr_8
returns the same value: 01011000
(which is just 88, the same returned by the first call of binstr_8
in the statement) In fact, when binstr_8
appears more than once in a printf
, every call returns 88? 当所谓
printf
与“最右边的位关”线的每个实例binstr_8
返回相同的值: 01011000
(这只是88,由第一次调用返回的相同binstr_8
在声明)事实上,当binstr_8
出现超过一旦进入printf
,每个调用都会返回88? (I even hardcoded the values) What is going on there? (我什至对值进行了硬编码)在那里发生了什么? Breaking the statements up such that each
printf
contains only a single call to binstr_8
works : 分手使得每个语句
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));
Output: 输出:
88 01011000 rightmost bit off: 01010000
88 01011000
87 01010111
& ---------
01010000
I can re-write the function as binstr_8_dyn
to dynamically allocate char *binstr
and then use the same printf
statements containing multiple calls to the function and it works . 我可以将函数
binstr_8_dyn
为binstr_8_dyn
以动态分配char *binstr
,然后使用相同的printf
语句,其中包含对该函数的多次调用,并且它可以正常工作 。 How is that possible? 那怎么可能? Example:
例:
/* 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));
The output is correct: 输出正确:
88 01011000 rightmost bit off: 01010000
88 01011000
87 01010111
& ---------
01010000
Now I have managed to totally confuse myself as to why binstr_8
cannot be called multiple times in the same printf
while binstr_8_dyn
can. 现在,我已成功地完全迷惑自己,为什么
binstr_8
不能在同一个被多次调用printf
同时binstr_8_dyn
即可。 What fundamental principle am I overlooking? 我忽略了什么基本原则? Also, how else would I provide the return without involving a global or passing a pointer other than using static or allocating dynamically?
另外,除了使用静态或动态分配外,我还应该如何提供返回而不涉及全局或传递指针?
当返回static
变量的地址并再次使用时,该值始终是相同的,并且它是最后一个已计算的值。
The binstr_8
function returns the same pointer every time - a pointer to your static buffer. binstr_8
函数每次都返回相同的指针-指向静态缓冲区的指针。
So if you pass it twice as argument to printf, printf receives the same buffer twice, therefore the same thing prints twice. 因此,如果将它两次作为参数传递给printf,则printf将两次接收相同的缓冲区,因此同一事物将打印两次。 Both calls to
binstr_8
run before printf
is called (a function's arguments must be evaluated before the function is called, obviously). 对
binstr_8
两次调用都在调用printf
之前运行(显然,必须在调用函数之前对函数的参数求值)。
The malloc
example returns a different buffer each time. 每次
malloc
示例都会返回一个不同的缓冲区。
Update : example of using multiple static buffers, inside the binstr_8
function: 更新 :在
binstr_8
函数内部使用多个静态缓冲区的binstr_8
:
static char binstr [5][CHAR_BIT + 1];
static char which = 0;
if ( ++which == 5 ) which = 0;
// use binstr[which] where you had binstr
Then you can use up to five calls to binstr_8
in each printf
. 然后,在每个
printf
您最多可以使用五个对binstr_8
调用。
You are returning a pointer to the static buffer so all of the binstrs point to the same memory location. 您将返回一个指向静态缓冲区的指针,因此所有binstr都指向相同的内存位置。 When you create a new one you are overwriting all of the existing binstrs.
创建新的二进制文件时,您将覆盖所有现有的二进制文件。 With binstr_dyn they are are different buffers.
对于binstr_dyn,它们是不同的缓冲区。 As all of your arguments are evaluated before the function call the printf prints the values of the last string created, which happens to be 88 because to order of evaluation of arguments is undefined.
由于在函数调用之前对所有参数进行了求值,因此printf会打印最后创建的字符串的值,该值恰好是88,因为对参数求值的顺序未定义。
binstr_8_dyn is the correct inplementation but you will neet to rember to free every string it creates. binstr_8_dyn是正确的填充,但是您将需要重新尝试释放它创建的每个字符串。
Adding to Matt McNabb's answer: 添加到Matt McNabb的答案中:
For a function like that the output string length can be determined in advance, so you can make a caller to allocate the output buffer. 对于这样的函数,可以预先确定输出字符串的长度,因此可以使调用方分配输出缓冲区。 Buffers can be automatic and you avoid problems with deallocation:
缓冲区可以是自动的,可以避免释放问题:
#define STR8LEN (sizeof (uint8_t) * CHAR_BIT)
#define STR8BUFLEN (sizeof (uint8_t) * CHAR_BIT + 1)
char *binstr_8 (uint8_t x, char *binstr)
{
size_t z;
size_t szstr = STR8LEN;
binstr [szstr] = 0;
for (z = 0; z < szstr; x >>= 1, z++)
binstr [szstr - 1 - z] = '0' + (x & 1);
return binstr;
}
void fun()
{
char buf1 [STR8BUFLEN], buf2 [STR8BUFLEN], buf3 [STR8BUFLEN];
printf (" 88 %s\n 87 %s\n & ---------\n %s\n\n",
binstr_8 (88, buf1), binstr_8 (87, buf2),
binstr_8 (88 & 87, buf3));
}
It's a caller function fun()
responsibility to allocate buffers prior to call and free them after use; 调用者函数
fun()
职责是在调用之前分配缓冲区,并在使用后释放它们; binstr_8
just uses them. binstr_8
只是使用它们。 Each time binstr_8
is called with a separate buffer, so the results do not overlap, and each call returns its own buffer as a result, so they can be used by printf. 每次使用单独的缓冲区调用
binstr_8
,结果不会重叠,并且每次调用都返回自己的缓冲区,因此printf可以使用它们。 You can also use them later, as they keep their contents as long as they exist (provided you do not overwrite them!): 您还可以稍后使用它们,因为它们会保留它们的内容,只要它们存在(只要您不覆盖它们!):
void fun()
{
char buf1 [STR8BUFLEN], buf2 [STR8BUFLEN], buf3 [STR8BUFLEN];
binstr_8 (88, buf1);
binstr_8 (87, buf2);
binstr_8 (88 & 87, buf3);
printf (" 88 %s\n 87 %s\n & ---------\n %s\n\n",
buf1, buf2, buf3);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.