snprintf/sprintf是否像strcat一样覆盖倒数第二个参数的终止null?

snprintf/sprintf是否像strcat一样覆盖倒数第二个参数的终止null?,c,concatenation,null-terminated,C,Concatenation,Null Terminated,它清楚地为strcat编写,例如 char *strcat(char *s1, const char *s2); 那么 s2的初始字符覆盖s1末尾的空字符 但显然,我在这里搜索了一下“C中串联字符串/文字”,我无意中发现 避免在C代码中使用strcat。最干净、最重要、最安全的方法是使用snprintf: 那么,对于snprintf/sprintf来说,下一个参数的第一个字符覆盖了前一个参数的空终止符,也是这样吗?我在报告中看不到这样的提法 经验证据似乎表明,strcat和snprintf的行

它清楚地为strcat编写,例如

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

s2的初始字符覆盖s1末尾的空字符

但显然,我在这里搜索了一下“C中串联字符串/文字”,我无意中发现

避免在C代码中使用strcat。最干净、最重要、最安全的方法是使用snprintf:

那么,对于
snprintf/sprintf
来说,下一个参数的第一个字符覆盖了前一个参数的空终止符,也是这样吗?我在报告中看不到这样的提法

经验证据似乎表明,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] = '\0';
    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] = '\0'; // not necessary as per documentation
    printf("snprintfResult:%s \tstrlen(snprintfResult):%d \tsizeof(snprintfResult):%d\n", 
            snprintfResult, 
            strlen(snprintfResult), 
            sizeof(snprintfResult));
    free(snprintfResult);
} 
#包括
#包括
int main(int argc,char const*argv[]
{
printf(“已启动测试程序”);
const char*first=“a”;
常量字符*second=“b”;
const char*third=“c”;
const int merged_length=(strlen(第一个)+strlen(第二个)+strlen(第三个)+1);//+1表示空终止
char*catResult;
catResult=malloc(合并长度*大小(字符));
strcpy(catResult,first);
strcat(catResult,第二);
strcat(catResult,第三);
catResult[merged_length]='\0';
printf(“catResult:%s\tstrlen(catResult):%d\t大小(catResult):%d\n”,
catResult,
斯特伦(catResult),
sizeof(catResult));
免费(catResult);
char*snprintfResult;
snprintfResult=malloc(合并长度*大小(字符));
snprintf(snprintfResult,合并长度,“%s%s%s”,第一、第二、第三);
//catResult[merged_length]='\0';//根据文档,不需要
printf(“snprintfResult:%s\tstrlen(snprintfResult):%d\tsizeof(snprintfResult):%d\n”,
斯普林特弗雷索,
斯特伦(snprintfResult),
sizeof(snprintfResult));
免费(snprintfResult);
} 
测试程序已启动
catResult:abc strlen(catResult):3个尺寸(catResult):4
snprintfResult:abc strlen(snprintfResult):3个尺寸(snprintfResult):4


snprintf
sprintf
不会像
strcat
那样附加到前面的字符串。它们从传递给它们的缓冲区开始写入

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


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

不能这样使用
sizeof
。虽然
sizeof(“string”)
的工作方式与您预期的一样,
sizeof(string指针)
在任何给定的平台上总是返回相同的值(通常为4或8)

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

应该是

const int merged_length=(strlen(第一)+strlen(第二)+strlen(第三)+1)

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


因此,您的问题的实际答案是否定的,因为null从来都不是在
第一个
之后写入的,但最终的效果更像是我们回答了“是”,因为这两个代码片段做的是相同的事情。

@user694733,wooops!我的错!我将编辑并更正它。一秒钟。@user694733,在我使用的PC上的原始测试代码中,
strlen
。然后我想用
sizeof
进行测试,但在粘贴到这里之前忘记了撤消更改。现在更好了吗?
snprintf
(类似于
strcat
)的错误用法是
snprintf(buf,buflen,“%s%s”,buf,更多内容)。这将在一些C库实现中“起作用”,而在其他C库实现中则不起作用,但根据标准,这是未定义的行为。@rici,好的。我理解。源和目标不能重叠,正如您在注释中的代码段所示。
当您将%s写入snprintf时,它会将字符串复制到目标字符串,而不会有任何尾随null。
-->这正是我的问题
因此,您的问题的实际答案是否定的,因为在第一次之后从未写入空值
-->感谢您的澄清。
在一次调用中写入多个字符串时,与格式字符串“%s%s”一样,他们将连续写入字符串,其间没有空字符
-->这正是我的问题。谢谢你的快速回答。