微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决snprintf / sprintf是否像strcat一样覆盖倒数第二个参数的终止空值?

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

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

然后

s2的起始字符覆盖s1末尾的空字符。

但是显然在这里搜索了“用C连接字符串/文字”,我偶然发现this,它指出,

避免在C代码中使用strcat。最干净,最重要的是,最安全的方法是使用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] = '\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);
} 

测试程序已启动
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)总是在任何给定平台上返回相同的值(通常为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。当到达格式字符串末尾的空终止符时,输出字符串也将以空终止。

因此,您的问题的实际答案是“否”,因为空值从未在first之后写入,但是最终效果更像是如果我们回答“是”,因为这两个代码片段都做同样的事情。 / p>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。