在函数中返回char *

时间:2010-03-14 13:18:14

标签: c function char

我有功能:

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;
}

主要有:

printf("%s", zap( argv[1] )  );

编译时我收到警告:

test.c: In function ‘zap’:
test.c:17: warning: function returns address of local variable

我该如何归还char *?

9 个答案:

答案 0 :(得分:18)

你最好的选择可能就是不要将它返回 - 而是将你想要填充的缓冲区作为参数传递给函数。

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);
}

然后这样称呼:

char pie[100];
zap( pie, "foo" );

要对此函数进行防范,您还需要传入缓冲区的长度,然后在每次要添加新查询元素时对其进行检查。

答案 1 :(得分:12)

发布的解决方案一切正常,但只是回答您的问题,为什么会收到警告:

当您在函数中将pie声明为缓冲区时,您没有分配堆内存,而是在堆栈中创建变量。该内存内容仅在该函数的范围内得到保证。一旦你离开函数(返回之后),该内存可以被重用,你可以找到你指向的内存地址随时被覆盖。因此,您将收到警告,您正在返回一个指向内存的指针,该指针无法保证可以保留。

如果要在可以在该函数外引用的c函数中分配持久性内存,则需要使用malloc(或其他类型的堆内存分配函数)。这将在堆上为该变量分配内存,并且它将持久直到使用free函数释放内存。如果你不清楚堆栈和堆内存,你可能想要谷歌,它会让你的C体验更顺畅。

答案 2 :(得分:4)

使用pie

malloc分配内存

答案 3 :(得分:4)

#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;
}

答案 4 :(得分:2)

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  );

答案 5 :(得分:2)

我强烈建议更改此功能,让用户传递缓冲区和长度,然后使用该缓冲区。或者,您可以分配返回值的新实例,即malloc,但请务必向用户发表评论以便再次释放。

答案 6 :(得分:1)

声明你的char数组静态

static char pie[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";

答案 7 :(得分:0)

略有不同的方法:

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;
}

此版本使用动态内存分配来根据需要调整缓冲区大小,从NULL缓冲区指针开始(realloc(NULL,size)== malloc(size))。这样您就不必担心开始使用“足够大”的缓冲区。唯一的缺点是你需要记住在你完成缓冲区时释放缓冲区(我通常不喜欢在这样的调用者和被调用者之间分配内存管理职责;如果我考虑它超过10分钟,我' d想出更好的东西)。

答案 8 :(得分:0)

我进行此类操作的方法是使本地缓冲区成为特定于线程的静态变量:

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;
}

我对专家的评论非常好奇。

不过,让我们暂时忘记缓冲区溢出问题。