snprintf/sprintf是否像strcat一样覆盖倒数第二个参数的终止null?
它清楚地为strcat编写,例如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的行
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”一样,他们将连续写入字符串,其间没有空字符
-->这正是我的问题。谢谢你的快速回答。