MrW*_*olf 30 c string return local-variables
我在3年多的时间里没有使用过C,我在很多方面都很生气.
我知道这可能看起来很愚蠢,但我现在无法从函数返回一个字符串.请假设:我不能string.h
用于此.
这是我的代码:
#include <ncurses.h>
char * getStr(int length)
{
char word[length];
for (int i = 0; i < length; i++)
{
word[i] = getch();
}
word[i] = '\0';
return word;
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我可以捕获字符串(使用我的getStr
函数)但我无法正确显示它(我得到了垃圾).
感谢帮助.
mic*_*yer 57
在调用者端的堆栈上分配字符串并将其传递给您的函数:
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
Run Code Online (Sandbox Code Playgroud)
或者将字符串设为静态getStr
:
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
Run Code Online (Sandbox Code Playgroud)
或者在堆上分配字符串:
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
Run Code Online (Sandbox Code Playgroud)
char word[length];
char *rtnPtr = word;
...
return rtnPtr;
Run Code Online (Sandbox Code Playgroud)
这个不好.您正在返回一个指向自动(作用域)变量的指针,该变量将在函数返回时被销毁.指针将指向一个被破坏的变量,这几乎肯定会产生"奇怪的"结果(未定义的行为).
您应该使用malloc
(例如char *rtnPtr = malloc(length)
)分配字符串,然后再将free
其分配main
.
您正在堆栈上分配字符串,然后返回指向它的指针。当你的函数返回时,任何堆栈分配都将变得无效;指针现在指向堆栈上的一个区域,该区域可能在下次调用函数时被覆盖。
为了执行您想要执行的操作,您需要执行以下操作之一:
malloc
,然后返回该指针。然后,调用者需要free
在内存使用完毕后进行调用。正如其他人已经说过的,如果不在堆上分配非常量字符串(例如使用 strdup),则无法以有用的方式返回非常量字符串。但在所有最新版本的 C 标准(C89 及更高版本,如果我没记错的话)中,您可以返回一个结构体。调用者不需要释放结果,因为它不在堆上。而且它是线程安全的。
#include <stdio.h>
struct stringbuf
{
char buf[40];
};
struct stringbuf getanswer(int i)
{
struct stringbuf result = { 0 };
snprintf(result.buf, sizeof(result.buf), "The answer is %d", i);
return result;
}
int main(int argc, char **argv)
{
/*
* Remember to pass the .buf member, not the struct, to functions
* such as printf which expect a character pointer as argument!
* Passing the result of getanswer in the next line without .buf
* appended, will likely crash the program because the program
* will put the entire struct on the stack, not a character
* pointer, and will make printf interpret the first few bytes
* of the string as a pointer. That would be bad.
*/
printf("How many arguments did I get? %s\n", getanswer(argc).buf);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
注意:为了使示例代码尽可能简单和集中,我只是声明了一个不带 typedef 的结构类型。通过使用 typedef 并返回定义的类型,您可以节省大量的打字时间。
有(可以说)一些缺点:
最后一点很重要,因为您必须记住带有字符数组的结构与数组本身不同。所以如果你想调用字符串函数,你应该传递字符串成员变量,而不是指向结构体的指针。这对于带有可变参数的函数(例如 printf 等)尤其重要,如果您做错了,编译器可能不会警告您:传递结构会将整个结构放在堆栈上,而不仅仅是指向第一个字符的指针。Printf 会将结构体中的前几个字符解释为字符指针,这肯定是无效的。
是的,可以将指向结构的指针强制转换为 char * 并将其传递给字符串函数(包括 printf),这样就可以正常工作,但我认为这样做是不好的做法:如果您(或其他人) )一旦决定将结构声明中的另一个成员变量放在字符串缓冲区前面,则任何使用指向结构的类型转换指针(假定字符串缓冲区从结构开始的位置开始)都会默默失败。您可能想避免这种情况,因此请使用指向字符串成员变量的指针,即使这有些不方便。
===江淮汽车
您的指针指向函数的局部变量。因此,一旦从函数返回,内存就会被释放。您必须在堆上分配内存才能在其他函数中使用它。
反而
char *rtnPtr = word;
做这个
char *rtnPtr = malloc(length);
这样就可以在主函数中使用了。使用后释放内存。