如何在C中返回ReadLine()函数?
我有点困在这里。。。当两次使用此如何在C中返回ReadLine()函数?,c,string,function,readline,C,String,Function,Readline,我有点困在这里。。。当两次使用此conReadLine()函数时,它返回的地址与我前面读取的第二个字符串相同。例如,如果它两次请求一个名称,我输入“NameA”和“NameB”,则存储的结果是“NameB”和“NameB”。我理解为什么会发生这种情况,但我不知道如何解决它。将“buffer”声明为static也会做同样的事情。如何让此函数在每个字符串上返回单独的地址 const char *conReadLine(void) { char buffer[MAX_BUFFER];
conReadLine()
函数时,它返回的地址与我前面读取的第二个字符串相同。例如,如果它两次请求一个名称,我输入“NameA”和“NameB”,则存储的结果是“NameB”和“NameB”。我理解为什么会发生这种情况,但我不知道如何解决它。将“buffer”声明为static也会做同样的事情。如何让此函数在每个字符串上返回单独的地址
const char *conReadLine(void)
{
char buffer[MAX_BUFFER];
fgets(buffer, MAX_BUFFER, stdin);
// Check for newline character.
char *newline = strchr(buffer, '\n');
if (newline)
*newline = '\0';
return buffer;
}
这是一部经典之作
函数返回指向内部变量(缓冲区)的指针。因此,基本上,您的数据位于内存(堆栈)的一部分,对其他函数的连续调用将覆盖它
在这种情况下,当您两次调用同一个函数时,变量的位置完全相同。因此,写入nameA
的内存将被nameB
和以下调用覆盖
更有趣的是:创建一个函数
const char *intermediate(void) {
char buffer[MAX_BUFFER];
return conReadLine();
}
第一次呼叫conReadLine,第二次呼叫intermediate。额外的函数调用和局部变量将“释放”内存位置,因此它将不再覆盖它
两种解决方案:
1) 不要将数据存储在静态定义的缓冲区中,而是使用malloc
从堆中获取一些内存(记住在不再需要时释放它)
2) 在第一次调用之后,将缓冲区的内容复制到另一个位置,以便在需要时可以对其进行分发
欢迎来到C指针的世界 这样做:
const char *conReadLine(void)
{
char buffer[MAX_BUFFER];
// something
return buffer;
}
正在返回指向解除分配堆栈的指针,这非常糟糕。它还带来了不可预知的结果,包括将同一地址与其他调用甚至其他函数一起重用
您需要这样做:
const char *conReadLine(void)
{
char *buffer = (char*)malloc(MAX_BUFFER);
// something
return buffer;
}
每次都会给你一个新的记忆位置。只需记住在使用完后释放它。要突出显示代码,请将所有行缩进4个空格。(还有,tabs?Ew.)代码猴子,是的。如果你想要更多,你就得付钱。我正在考虑用它自己的内存分配缓冲区并返回它。但这也可能会产生一些有趣的bug。为什么它有C++标签?C++的方式会有很大的不同。2是不可接受的。返回指向自动内存的指针是不正确的。正确的方法是将缓冲区(在自动存储中)及其长度作为参数传递,并在函数中将数据复制到该缓冲区中。是的。强烈建议在生产中使用选项1。但是,如果您想了解它是如何工作的,请检查解决方案2。我可以看到它是如何“工作”的,而不是。这就像OP的解决方案一样,是一种未定义的行为,而它确实对您有效这一事实是一种侥幸。当存在一个定义更明确(并且从复制的数据量来看成本更低)的选项时,没有理由使用这个选项。如果你喜欢摆弄闪烁灯和旋钮,这就是C很有趣的原因之一。你必须认真思考你在做什么,否则结果会一团糟。编写C代码时不允许松懈。学习很好。学习正确的方法更好。为什么当你能教正确的方法时教错了方法?在C中有些人认为将代码返回> MalOC/<代码>的返回值是不好的做法,但是+1是第一个说“返回堆栈内存是坏的”。Chris Lutz:为什么他们认为这是一个坏的实践?仅仅因为它不是必需的?如果您忘记了
#包含,malloc
被隐式声明为int malloc(size\u t)
,这在sizeof(int)
的平台上是一个问题,指针值将被自动截断,可能会破坏malloc
返回的所有指针。此外,如果缓冲区的类型更改(例如,更改为wchar\u t
),您还必须更改强制转换。这可能会变得很乏味,尤其是如果您经常使用malloc
和realloc
char*buffer=malloc(BUFSIZE*sizeof*buffer)
将起作用,无论buffer
更改为什么类型。@Chris Lutz:malloc是隐式定义的吗?它应该来自libc,libc是平台的,甚至是特定于配置的,这是编译器不应该知道的。调用int malloc(size\u t)
与调用void*malloc(size\u t)
堆栈不同,因此它们无法在x64平台上组合在一起。不,它不是隐式定义的。如果您忘记了#包含
,则在您首次使用malloc
时,根据C89规则,它将隐式声明为返回一个int
。调用没有什么不同,只是返回值不同,这就是为什么如果隐式声明(在意外情况下)生成的程序集将是错误的。幸运的是,GCC在隐式声明标准库函数时发出警告,但并非所有编译器都发出警告。