我已经学习了几个星期的C.我通过使用malloc()
在堆上分配一些内存来解决我的问题。我清楚地知道为什么我的代码失败但我不是百分百肯定。不幸的是,我是自学成才,所以我不得不求助于互联网上善良的人。
代码说明调用声明数组的函数getString()
,使用内置getchar()
填充数组并返回指向该数组的指针。
问题我打印返回的指针值,一切都很好。但是当我将它传递给另一个简单地将其吐出并尝试打印的函数时,字符串的末尾被切断,有时会吐出一个无意义的字符。
我认为可能发生的事情原始数组仅在getString()函数&所以C使用数组地址中的一些内存来存储其他东西。
我的直觉是否正确?如果没有,有人指向我的方向正确吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100
char * getString(void);
char * doSomethingWith(char *);
int main(void)
{
char *string1 = getString();
printf("String: %s\n", string1);
char *string2 = doSomethingWith(string1);
printf("String: %s\n", string2); // This print out is unreliable!
return EXIT_SUCCESS;
}
char * getString(void) {
int c;
char arr[MAXLEN];
char *string = arr;
char *cur = arr;
while((c = getchar()) != '\n' && c != EOF) {
if(cur - string < MAXLEN - 2) {
*cur++ = c;
}
}
*cur = '\0'; // Terminate string
return string;
}
char * doSomethingWith(char *string) {
return string;
}
这是我修正的getString(),它的行为正确。
char * getString(void) {
int c;
char *string = malloc(sizeof *string * MAXLEN);
char *cur = string;
while((c = getchar()) != '\n' && c != EOF) {
if(cur - string < MAXLEN - 2) {
*cur++ = c;
}
}
*cur = '\0'; // Terminate string
return string;
}
更新:感谢您的所有答案!非常感谢。
答案 0 :(得分:1)
getString
返回具有自动存储持续时间的函数局部变量的地址,地址为arr
。在函数返回后通过该地址访问arr
的任何尝试都有未定义的行为。
C标准无法保证它会保留其价值。不能保证不会。当你打破像这样的语言约束时,编译器没有义务甚至生成有效的程序。
6.2.4 Storage durations of objects ¶2
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储。一个对象存在,具有一个常量地址,33)并在其整个生命周期内保留其最后存储的值.34)如果一个对象在其生命周期之外被引用,则该行为是未定义的。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。
上面提到的生命周期是从开始大括号到getString
的右大括号,只要它只执行。不多也不少。
答案 1 :(得分:1)
char *string = arr;
错误,因为没有为arr
分配内存;它是堆栈中的变量。返回时,堆栈内存被重新启动,因此您返回一个指向已释放变量的指针。
使用malloc
代替,例如:
string= malloc(strlen(arr)+1);
strcpy(string,arr);
return string;