sprintf 的最佳实践?

Wil*_*olf 9 c standards pointers restrict-qualifier asprintf

情况是这样的:

我们从外部源收到了使用 sprintf(如 strcat)的代码。像这样:

char buffer[1024];
sprintf(buffer, "Some text.");
sprintf(buffer, "%s%s", buffer, "Some more text");
sprintf(buffer, "%s%s", buffer, "again more text");
Run Code Online (Sandbox Code Playgroud)

现在,这看起来很奇怪。我们都同意这看起来很奇怪。我要问的不是这个。我们都知道应该用strcat,而且更直接。我问的是除了看起来很奇怪之外,这可能导致的潜在问题。我们在 RHEL6 上运行,并使用 gcc 4.9.3。

感谢您的帮助。

Vla*_*cow 11

该函数声明如下

int sprintf(char * restrict s, const char * restrict format, ...);
Run Code Online (Sandbox Code Playgroud)

注意类型限定符restrict

根据 C 标准(7.21.6.6 sprintf 函数)

2 sprintf 函数与 fprintf 等效,只是输出被写入数组(由参数 s 指定)而不是流中。写入的字符末尾写入空字符;它不计入返回值的一部分。 如果复制发生在重叠的对象之间,则行为是未定义的

所以这些电话

sprintf(buffer, "%s%s", buffer, "Some more text");
sprintf(buffer, "%s%s", buffer, "again more text");
Run Code Online (Sandbox Code Playgroud)

调用未定义的行为。

相反,调用可以写成这样

char buffer[1024];
int offset = 0;

offset = sprintf( buffer + offset, "Some text.");
offset += sprintf( buffer + offset, "%s",  "Some more text");
sprintf( buffer + offset, "%s",  "again more text");
Run Code Online (Sandbox Code Playgroud)

或者

char buffer[1024];
char *p = buffer;

p += sprintf( p, "Some text.");
p += sprintf( p, "%s",  "Some more text");
sprintf( p, "%s",  "again more text");
Run Code Online (Sandbox Code Playgroud)

至于限定符restrict,一般来说是指意思(6.7.3 类型限定符)

8 通过限制限定指针访问的对象与该指针具有特殊关联。这种关联在下面的 6.7.3.1 中定义,要求对该对象的所有访问都直接或间接地使用该特定指针的值