C语言 在函数中返回 char*
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2442239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Returning char* in function
提问by Devel
I have function:
我有功能:
char *zap(char *ar) {
char pie[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
return pie;
}
and in main there is:
主要有:
printf("%s", zap( argv[1] ) );
When compiling I get the warning:
编译时我收到警告:
test.c: In function ‘zap':
test.c:17: warning: function returns address of local variable
How should I return char* propertly?
我应该如何正确返回 char* ?
回答by
Your best bet probably is not to return it at all - instead, pass the buffer you want to populate into the function as a parameter.
最好的办法可能是根本不返回它 - 相反,将要填充的缓冲区作为参数传递到函数中。
void zap(char * pie, const char *ar) {
strcpy( pie, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '");
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
}
Then call it like this:
然后像这样调用它:
char pie[100];
zap( pie, "foo" );
To bullet proof this function, you also need to pass in the length for the buffer, and then check against this every time you are about to add a new query element.
为了防弹这个函数,您还需要传入缓冲区的长度,然后在每次要添加新的查询元素时进行检查。
回答by Myke
The posted solutions all work, but just to answer your question as to why you get a warning:
发布的解决方案都有效,但只是为了回答您关于为什么收到警告的问题:
When you declare pie as buffer in the function, you are not allocating heap memory, the variable is being created in the stack. That memory content is only guaranteed within the scope of that function. Once you leave the function (after the return) that memory can be reused for anything and you could find that memory address you are pointing at overwritten at any time. Thus, you are being warned that you are returning a pointer to memory that is not guaranteed to stick around.
当您在函数中将 pie 声明为缓冲区时,您不是在分配堆内存,而是在堆栈中创建变量。该内存内容仅在该功能范围内得到保证。一旦您离开该函数(返回后),该内存就可以重新用于任何事情,并且您可以随时发现您指向的内存地址被覆盖。因此,您会被警告说您正在返回一个指向内存的指针,该指针不保证会一直存在。
If you want to allocate persistent memory in a c function that you can reference outside that function, you need to use malloc (or other flavors of heap memory allocation functions). That will allocate the memory for that variable on the heap and it will be persistent until the memory is freed using the free function. If you aren't clear on stack vs. heap memory, you may want to google up on it, it will make your C experience a lot smoother.
如果要在 ac 函数中分配可以在该函数外部引用的持久内存,则需要使用 malloc(或其他类型的堆内存分配函数)。这将在堆上为该变量分配内存,并且在使用 free 函数释放内存之前它将一直存在。如果您不清楚堆栈内存与堆内存,您可能想搜索一下,它会让您的 C 体验更加流畅。
回答by Nemanja Trifunovic
Allocate the memory for piewith malloc
为piewith分配内存malloc
回答by Roland Illig
#include <assert.h>
#include <stdio.h>
/**
* Returns the buffer, just for convenience.
*/
char *generateSQL(char *buf, size_t bufsize, const char *ar) {
int n;
n = snprintf(buf, bufsize, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '%s')", ar);
/* FIXME: Properly escape the argument, just in case it contains an apostrophe. */
assert(0 <= n && (unsigned) n < bufsize);
return buf;
}
int main(int argc, char **argv)
{
char buffer[4096];
assert(1 < argc);
printf("%s\n", generateSQL(buffer, sizeof(buffer), argv[1]));
return 0;
}
回答by James
char pie[100];
void zap(char* pie, char *ar) {
char pies[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
char dru[] = "' )";
strcpy(pie, pies);
strcat(pie, ar);
strcat(pie, dru);
}
zap(pie, argv[1]);
printf("%s", pie );
回答by Tommy Andersen
I would strongly suggest changing this function, let the user pass a buffer and a length as well and use that buffer instead. Alternatively you can allocate a new instance of the return value i.e. with mallocbut make sure to leave a comment to the user to free it again.
我强烈建议更改此函数,让用户同时传递缓冲区和长度,然后改用该缓冲区。或者,您可以分配一个新的返回值实例,即 withmalloc但一定要给用户留下评论以再次释放它。
回答by knittl
declare your char array static
将您的字符数组声明为静态
static char pie[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
回答by John Bode
Slightly different approach:
略有不同的方法:
void zap(char **stmt, char *argument, size_t *stmtBufLen)
{
char *fmt="INSERT INTO test(nazwa, liczba) VALUES ('nowy wpis', '%s')";
/**
* Is our current buffer size (stmtBufLen) big enough to hold the result string?
*/
size_t newStmtLen = strlen(fmt) + strlen(argument) - 2;
if (*stmtBufLen < newStmtLen)
{
/**
* No. Extend the buffer to accomodate the new statement length.
*/
char *tmp = realloc(*stmt, newStmtLen + 1);
if (tmp)
{
*stmt = tmp;
*stmtLen = newStmtLen+1;
}
else
{
/**
* For now, just write an error message to stderr; the statement
* buffer and statement length are left unchanged.
*/
fprintf(stderr, "realloc failed; stmt was not modified\n");
return;
}
}
/**
* Write statement with argument to buffer.
*/
sprintf(*stmt, fmt, argument);
}
int main(void)
{
char *stmtBuffer = NULL;
size_t stmtBufferLen = 0;
...
zap(&stmtBuffer, "foo", &stmtBufferLen);
...
zap(&stmtBuffer, "blurga", &stmtBufferLen);
...
zap(&stmtBuffer, "AReallyLongArgumentName", &stmtBufferLen);
...
zap(&stmtBuffer, "AnEvenLongerRidiculouslyLongArgumentName", &stmtBufferLen);
...
free(stmtBuffer);
return 0;
}
This version uses dynamic memory allocation to resize the buffer as needed, starting with a NULL buffer pointer (realloc(NULL, size) == malloc(size)). This way you don't have to worry about starting out with a buffer that's "big enough". The only drawback is you need to remember to deallocate the buffer when you're done with it (I don't normally like splitting memory management duties between caller and callee like this; if I thought about it for more than 10 minutes, I'd come up with something better).
此版本使用动态内存分配根据需要调整缓冲区大小,从 NULL 缓冲区指针 (realloc(NULL, size) == malloc(size)) 开始。这样您就不必担心从“足够大”的缓冲区开始。唯一的缺点是你需要记住在完成后释放缓冲区(我通常不喜欢像这样在调用者和被调用者之间分配内存管理职责;如果我考虑了超过 10 分钟,我' d 想出更好的东西)。
回答by Janusz Lenar
The way I do such manipulations is making local buffer a static thread-specific variable:
我进行此类操作的方式是使本地缓冲区成为静态线程特定变量:
const int max_pie_cnt = 100;
const char *zap(char *ar) {
static __declspec(thread) char pie[max_pie_cnt]; // use TLS to store buffer
strcpy(pie, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '");
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
return pie;
}
I'm very curious about experts' comments.
我很好奇专家的评论。
Btw, let's forget about buffer overflow problem for a moment.
顺便说一句,让我们暂时忘记缓冲区溢出问题。

