I'm having trouble printing a member of a struct that is returned from a function:
#include <stdio.h>
struct hex_string
{
char a[9];
};
struct hex_string to_hex_string_(unsigned x)
{
static const char hex_digits[] = "0123456789ABCDEF";
struct hex_string result;
char * p = result.a;
int i;
for (i = 28; i >= 0; i -= 4)
{
*p++ = hex_digits[(x >> i) & 15];
}
*p = 0;
printf("%s\n", result.a); /* works */
return result;
}
void test_hex(void)
{
printf("%s\n", to_hex_string_(12345).a); /* crashes */
}
The printf
call inside to_hex_string_
prints the correct result, but the printf
call inside test_hex
crashes my program. Why exactly is that? Is it a lifetime issue, or is it something else?
When I replace the printf
call with puts(to_hex_string_(12345).a)
, I get a compiler error:
invalid use of non-lvalue array
What's going on here?
There is a rule in C which seldom comes into effect, which states:
If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined. (C99 §6.5.2.2)
In this case, there is a sequence point after the arguments to printf()
are evaluated and before the printf()
function itself executes. The pointer you pass to printf()
is a pointer to an element of the return value itself - and when printf()
tries to access the string through that pointer, you get your crash.
This issue is hard to run into, because a function value isn't an lvalue so you can't directly take a pointer to it with &
.