C:printf(“%s \ n”,str)产生乱码?

时间:2019-05-24 23:38:18

标签: c string pointers printf

我有一些应该调用函数并返回字符串的C代码。我在某个地方读到这很困难,因为内存分配不恒定或什么?无论如何,我被告知我宁愿将指针返回到字符串。但是,我无法解释为什么printf有时会产生乱码,有时却不会:

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

char * execTasks() {

    int d, m, y;
    char str[6] = {};

    d = 10; m = 5; y = 18;

    memset(&str, 0, sizeof(str));
    sprintf(str, "%02d%02d%02d", d, m, y);
    printf("Works fine: %s\n", str); // Works fine even with additions

    char *s_ptr = str;
    return s_ptr; 
}

int main() {

    char * str;

    str = execTasks();

    printf("%s", str); // works fine!
    printf("%s\n", str); // produces gibberish!
    printf("%s,%s", str, str); // also gibberish!

    return 0;
}

有人可以向我解释为什么printf("%s", str);可以正常工作,而printf("%s\n", str);和变化形式却显示出乱码吗?

还是我在返回指针时做错了什么?本质上,该函数应以字符串DDMMYY的格式返回日期。稍后我需要在main函数中将此字符串附加到另一个字符串。

1 个答案:

答案 0 :(得分:2)

数组char str[6]execTasks函数的本地。 execTasks返回之后,该内存将被回收,并且可以由其他代码使用。碰巧printf中的最后两个main使用了该内存并破坏了字符串,而printf中的第一个main没有使用。但是,此代码仍然无效(如“未定义行为”),因为在适当的情况下(例如,不同的编译器,体系结构或标准库实现),它也会产生乱码或崩溃。

要解决的问题是,您不应返回指向局部变量的指针,而应使用动态分配的字符串副本:

char * execTasks() {
    int d, m, y;
    char str[7] = {};
    // ...
    return strdup(str); // mallocs a copy of str
}

int main() {
    char * str = execTasks();
    printf("%s,%s", str, str);
    free(str); // reclaim memory
}

或使用main局部变量:

int execTasks(char *str, size_t size) {
    int d, m, y;
    d = 10; m = 5; y = 18;
    return snprintf(str, size, "%02d%02d%02d", d, m, y);
}

int main() {
    char str[7];
    execTasks(str, sizeof(str));
    printf("%s,%s", str, str);
}

此处execTasks返回保存结果所需的字符数(不包括空终止符)。它可以用来检测何时提供的缓冲区太小,尽管在这个简单的示例中我没有这样做(如果太小,字符串将被截断)。

还请注意,字符串所需的内存量为七个char,因为您需要为空终止符增加一个字节。