我有一组函数都构建了这样的日志字符串:
...
// Top level snprintf call
snprintf(buffer, BUFSIZ, "%s %s %s", dump_1(obj), dump_2(obj), dump_3(obj));
...
static char *dump_1(my_own_type_t obj)
{
static char t1[BUFSIZ];
// Logic printing obj data into t1
return t1;
}
static char *dump_2(my_own_type_t obj)
{
static char t2[BUFSIZ];
// Logic printing obj data into t2
return t2;
}
static char *dump_3(my_own_type_t obj)
{
static char t3[BUFSIZ];
// Logic printing obj data into t3
return t3;
}
这是一种很好的方法,还是有更好的方法来实现同样的目标?我可以使用动态分配的字符串,但后来我必须添加内存管理,这将使代码更复杂。我也可以传递缓冲区,然后直接写入缓冲区,但这意味着需要大量额外的snprintf调用,因为每次我想在字符串中添加内容时都要调用snprintf。
编辑: 在我的情况下,线程安全不是问题,并且日志记录调用不是可重入的。所以从理论上讲,我可以保持原样。然而,根据mcleod_ideafix的建议,以某种方式感觉更干净。这样我就不需要任何静态变量了,我仍然会将snprintf调用保持在最低限度。唯一的缺点是声明了很多本地缓冲区,但我觉得这在我的情况下是可控的。非常感谢所有的反馈。
答案 0 :(得分:6)
只要您意识到它使函数不可重入,返回指向静态的指针就可以了。所以,例如,
snprintf(buffer, BUFSIZ, "%s %s", dump_1(obj1), dump_1(obj2));
将失败,因为对dump_1()的两次调用将会发生干扰,并且可能无法按您期望的顺序调用。此外,您将无法使用线程代码中的函数。通用字符串函数的最佳实践是将输出字符串和大小作为参数传递,就像snprintf一样。
答案 1 :(得分:1)
这是一种非常有效的返回字符串的方法。
然而,然而,在每种情况下,这都不是正确的方法。首先,如果你的函数是从多个线程调用的,那么它们都将使用相同的缓冲区并相互覆盖。
答案 2 :(得分:1)
我也可以传递缓冲区,然后直接写入 缓冲区,但这意味着我会进行大量额外的snprintf调用 每当我想要添加东西时,都必须调用snprintf 字符串。
不必要:
...
char s1[BUFSIZ],s2[BUFSIZ],s3[BUFSIZ];
...
// Top level snprintf call
snprintf(buffer, BUFSIZ, "%s %s %s", dump_1(obj,s1), dump_2(obj,s2), dump_3(obj,s3));
...
//or like this:
...
dump_1(obj,s1);
dump_2(obj,s2);
dump_3(obj,s3);
snprintf(buffer, BUFSIZ, "%s %s %s", s1, s2, s3);
...
char *dump_1(my_own_type_t obj, char *s)
{
// Logic printing obj data into s
return s;
}
char *dump_2(my_own_type_t obj, char *s)
{
// Logic printing obj data into s
return s;
}
char *dump_3(my_own_type_t obj, char *s)
{
// Logic printing obj data into s
return s;
}
第二种方式还允许您清楚地建立不同dump_X()
函数的执行顺序,如果在snprintf()
参数评估中调用它们可能不清楚(事实上,第一种方法)方式可能先调用dump_3()
,然后调用dump_2()
然后调用dump_1()
,因为C_decl
函数在堆栈中推送其参数的方式:从右到左。你可能或者可能不关心它)
答案 3 :(得分:0)
返回指向函数本地静态数组的指针并不是一种好方法。将变量设为静态只是为下一次函数调用修正它的值。
如果你声明一个指向char的指针,那么函数返回的值会定义一个新的指针,并为它指定同一函数返回的值。这将使两个指针指向同一个地址并更改存储在其中一个指针指向的地址中的值,使其更改为另一个指针,因为它们指向同一个地址,如下例所示:
int i = 1;
static char *f()
{
static char a[10];
if (i){
strcpy(a, "value 1");
i = 0;
}
else {
strcpy(a, "value 2");
}
return a;
}
int main()
{
char *x1 = f();
char *x2 = f();
printf("%s\n", x1);
printf("%s\n", x2);
return 0;
}
输出结果为:
value 2
value 2
相反,最好的方法是在函数内声明一个指针并为内容分配内存