3 ms·
Preloading a version that alternates between two buffers is clearly Wrong, but I'm not sure what the right solution is - do you/does anyone have a pattern that
by JoachimSchipper 12y ago
Preloading a version that alternates between two buffers is clearly Wrong, but I'm not sure what the right solution is - do you/does anyone have a pattern that they find works well for them?
Our codebase has quite a few functions like inet_ntoa():
/* returns ptr. to internal static storage */
const char *type_to_str(const Type *type);
You could pass an explicit argument, but that's pretty ugly:
/* Explicit buffer argument */
char msg_buf1[256], msg_buf2[256], msg_buf3[256], ..., msg_buf16[256];
char *type_to_str(char *buf_to_use, size_t buf_size, const Type *type)
Alternatively, you could give C99 a workout and abuse compound literals as anonymous storage:
#include <stdio.h>
struct foo {
int bar;
};
#define FOO_TO_STR_SIZE 256
#define foo_to_str(foo) \
foo_to_str_((char [FOO_TO_STR_SIZE]){ 0 }, FOO_TO_STR_SIZE, (foo))
/* Implementation detail */
__attribute__((nonnull))
static char *foo_to_str_(char *buf_to_use, size_t size,
const struct foo *foo)
{
(void)snprintf(buf_to_use, size, "%d", foo->bar);
return buf_to_use;
}
int main(void)
{
const struct foo foo = {
.bar = 42
}, foo2 = {
.bar = 43
};
printf("%s %s\n", foo_to_str(&foo),
foo_to_str(&foo2));
return 0;
}
(Warning: this is probably too clever. Note that you need the explicit size argument if you offer a library, or you risk your callers using a different FOO_TO_STR_SIZE than you do. There is probably a very minor performance penalty to this solution as the caller must, in general, completely initialize the string. Note the gcc warnings about compound literals in C++ - see https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html for a discussion.)
- justincormack 12y agoreturning a const char is absolutely fine - I assume your type name is allocated when the type is and never changes, and you have locking if necessary.
- tptacek 12y agoIt's morally wrong, but since you usually only ever want to print two IP addresses, it feels so right. In any case: it can't break otherwise-correct code.
- caf 12y agoI don't see what's ugly about passing a buffer and size. That's exactly what inet_ntoa()'s modern replacement inet_ntop() does.