snprintf/sprintf 是否会覆盖倒数第二个参数的终止空值,就像 strcat 一样?

Does snprintf/sprintf overwrite the terminating-null of the penultimate argument, just like strcat does?

显然是为strcat写的,例如here and here 以防万一,

char *strcat(char *s1, const char *s2);

然后,

The initial character of s2 overwrites the null character at the end of s1.

但显然在这里搜索了一些“在 C 中连接 strings/literals”,我偶然发现了 this,其中指出,

Avoid using strcat in C code. The cleanest and, most importantly, the safest way is to use snprintf:

那么,对于 snprintf/sprintf 来说, 下一个参数的第一个字符覆盖前一个参数的空终止符 也是如此吗?我在 documentation.

中看不到这样的引用

经验证据似乎表明,strcat 和 snprintf 的行为方式相同。还是我的假设错了?

#include <string.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    printf( "Test Program Started\n");
    const char* first = "a";
    const char* second = "b";
    const char* third = "c";
    const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1); // +1 for null-termination

    char* catResult;
    catResult = malloc( merged_length * sizeof(char));
    strcpy(catResult, first);
    strcat(catResult, second);
    strcat(catResult, third);
    catResult[merged_length] = '[=12=]';
    printf("catResult:%s \tstrlen(catResult):%d \t sizeof(catResult):%d\n", 
            catResult, 
            strlen(catResult), 
            sizeof(catResult));
    free(catResult);

    char* snprintfResult;
    snprintfResult = malloc( merged_length * sizeof(char));
    snprintf(snprintfResult, merged_length, "%s%s%s", first, second, third);
    // catResult[merged_length] = '[=12=]'; // not necessary as per documentation
    printf("snprintfResult:%s \tstrlen(snprintfResult):%d \tsizeof(snprintfResult):%d\n", 
            snprintfResult, 
            strlen(snprintfResult), 
            sizeof(snprintfResult));
    free(snprintfResult);
} 

Test Program Started
catResult:abc strlen(catResult):3 sizeof(catResult):4
snprintfResult:abc strlen(snprintfResult):3 sizeof(snprintfResult):4

snprintfsprintf 不像 strcat 那样附加到先前的字符串。他们在传递给他们的缓冲区的开头开始写入。

在一次调用中写入多个字符串时,与格式字符串"%s%s%s"一样,它们将连续写入字符串,它们之间没有空字符,并以空字符结尾。

如果您希望它们附加到名为 buffer 的缓冲区中的现有字符串,则确定字符串的长度,例如 n,并将 buffer + n 作为第一个传递参数而不是 buffer。 (对于 snprintf,请注意还应从第二个参数中减去 n,该参数指定缓冲区中可用的字节数。)

你不能那样使用 sizeof。虽然 sizeof("string") 如您所愿,但 sizeof(string pointer) 在任何给定平台上总是 returns 相同的值(通常为 4 或 8)。

const int merged_length = (sizeof(first) + sizeof(second) + sizeof(third) + 1);

应该是

const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1);

当您将 %s 写入 snprintf 时,它会将字符串复制到目标字符串,不带任何尾随空值。当到达格式字符串末尾的 null 终止符时,输出字符串也以 null 终止。

所以,你的问题的实际答案是否定的,因为null在first之后从来没有写过,但最终的效果更像是我们回答是的,因为这两个代码片段做同样的事情.