为什么snprintf改变第二个字符串?

时间:2017-02-10 11:04:49

标签: c printf c-strings

我正在尝试使用snprintf连接两个字符串,它适用于非常小的字符串,例如。 1或2个字符,更多,这种事情发生。重复第一个字符串的最后一个字符

int main()
{
    char str1[] = "foo", str2[] = "bar", str3[]= "";

    printf("%s %s\n", str1, str2);

    snprintf(str3, strlen(str1) + strlen(str2) + 1, "%s %s", str1, str2);

    printf("%s", str3);

    return 0;
}

输出:

foo bar
foo oo

1 个答案:

答案 0 :(得分:3)

您的代码存在的问题是str3不足以容纳str1str2

由于您使用str3初始化""str3的大小将设置为1

这是正确的方法:

#include <stdio.h>  // snprintf
#include <stdlib.h> // malloc, free
#include <string.h> // strlen

int main() {
    char str1[] = "foo";
    char str2[] = "bar";
    // We need to dynamically allocate the third buffer
    // since its size is not determined at compile time.
    // The size we need is the length of str1, str2, + 1 for a space
    // and + 1 for the NUL terminator.
    size_t str3_size = strlen(str1) + strlen(str2) + 2;

    char *str3 = malloc(str3_size);

    // NULL = out of memory
    if (!str3) {
        printf("oops!"); return EXIT_FAILURE;
    }

    snprintf(str3, str3_size, "%s %s", str1, str2);

    printf("%s", str3);

    // Don't forget to free malloc'd memory!
    free(str3);
}

如果您使用的是C99编译器,您可以完全删除malloc并在堆栈上分配第三个缓冲区,如下所示:

#include <stdio.h>  // snprintf
#include <stdlib.h> // EXIT_FAILURE
#include <string.h> // strlen

int main() {
    char str1[] = "foo";
    char str2[] = "bar";
    // The size we need is the length of str1, str2, + 1 for a space
    // and + 1 for the NUL terminator.
    size_t str3_size = strlen(str1) + strlen(str2) + 2;

    char str3[str3_size];

    snprintf(str3, str3_size, "%s %s", str1, str2);

    printf("%s", str3);
}

但是要小心,在堆栈上分配动态大小的内存可能很危险!

还有一个函数asprintf(GNU扩展名),可自动计算正确的大小。这里有相同的例子:

#include <stdio.h>  // asprintf
#include <stdlib.h> // free

int main() {
    char str1[] = "foo";
    char str2[] = "bar";
    char *str3 = NULL;

    asprintf(&str3, "%s %s\n", str1, str2);
    // str3 now contains a pointer to the allocated memory :)

    // NULL = out of memory
    if (!str3) {
        printf("oops!"); return EXIT_FAILURE;
    }

    printf("%s", str3);

    // Don't forget to free malloc'd memory!
    free(str3);
}