从C函数返回string
三年多来我一直没有用过C,很多东西我都生锈了。
我知道这可能看起来很愚蠢,但我现在不能从函数返回一个string。 请假定:我不能使用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; }
我可以捕获string(用我的getStr
函数),但我不能让它正确显示(我得到垃圾)。
帮助表示赞赏。
要么在调用者端分配栈上的string,并将其传递给你的函数:
void getStr(char *wordd, int length) { ... } int main(void) { char wordd[10 + 1]; getStr(wordd, sizeof(wordd) - 1); ... }
或者让getStr
的string为静态:
char *getStr(void) { static char wordd[10 + 1]; ... return wordd; }
或者在堆上分配string:
char *getStr(int length) { char *wordd = malloc(length + 1); ... return wordd; }
char word[length]; char *rtnPtr = word; ... return rtnPtr;
不是很好。 您正在返回一个指向自动(范围)variables的指针,该函数在函数返回时将被销毁。 指针将被指向一个被破坏的variables,这几乎肯定会产生“奇怪的”结果(未定义的行为)。
你应该用malloc
分配string(例如char *rtnPtr = malloc(length)
),然后在main
free
它。
您正在堆栈中分配您的string,然后返回一个指针。 当你的函数返回时,任何堆栈分配都会失效。 现在指针指向堆栈上的一个区域,下次调用某个函数时可能会覆盖该区域。
为了做你想做的事情,你需要做以下的一件事:
- 使用
malloc
或类似方法在堆上分配内存,然后返回该指针。 当存储器完成后,调用者将需要free
呼叫。 - 在调用函数(将使用string的函数)中的堆栈上分配string,并将指针传递给该函数以放入string。 在调用函数的整个调用过程中,堆栈中的数据是有效的; 它只有一次你返回的那个堆栈分配的空间被其他东西所使用。
word
在堆栈上并在getStr()
返回时超出范围。 您正在调用未定义的行为。
你的指针指向函数的局部variables。 所以只要你从函数返回,内存就会被释放。 您必须在堆上分配内存才能在其他函数中使用它。
char *rtnPtr = word;
做这个char *rtnPtr = malloc(length);
这样它在主要function中可用。 使用后释放内存。
更容易:返回一个指向已被malloc'd strdup的string的指针。
#include <ncurses.h> char * getStr(int length) { char word[length]; for (int i = 0; i < length; i++) { word[i] = getch(); } word[i] = '\0'; return strdup(&word[0]); } int main() { char wordd[10]; initscr(); *wordd = getStr(10); printw("The string is:\n"); printw("%s\n",*wordd); getch(); endwin(); return 0; }
我在了解Cython的同时,遇到了这个线程。 我对原始问题的扩展可能对在C / Cython接口工作的其他人有用。 所以这是原始问题的扩展:我如何从C函数返回一个string,使它可用于Cython和Python?
对于那些不熟悉它的人,Cython允许你静态地input你需要加速的Python代码。 所以这个过程是,喜欢编写Python :),在某个地方find它有点慢,分析它,产生一个或两个函数,并将它们集成到一起。 哇。 接近C速度(编译为C)固定。 好极了。 另一个用途是将C函数或库导入到Python中,就像这里所做的那样。
这将打印一个string并将相同或另一个string返回给Python。 有3个文件,c文件c_hello.c,cython文件sayhello.pyx和cython安装文件sayhello.pyx。 当它们使用python setup.py build_ext --inplace
进行编译时,它们会生成一个共享库文件,该文件可以导入到python或ipython中,并运行sayhello.hello函数。
c_hello.c
#include <stdio.h> char *c_hello() { char *mystr = "Hello World!\n"; return mystr; // return "this string"; // alterative }
sayhello.pyx
cdef extern from "c_hello.c": cdef char* c_hello() def hello(): return c_hello()
setup.py
from setuptools import setup from setuptools.extension import Extension from Cython.Distutils import build_ext from Cython.Build import cythonize ext_modules = cythonize([Extension("sayhello", ["sayhello.pyx"])]) setup( name = 'Hello world app', cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules )