【问题标题】:Best way to create a string in C and pass it down function to function?在 C 中创建字符串并将其传递给函数的最佳方法是什么?
【发布时间】:2019-08-12 21:12:57
【问题描述】:

我想创建一个字符串并将其传递给函数以在它被修改时运行。我想实现这种编写最少的代码。最好的方法是什么?

下面的 sn-p 是我对这个问题的看法。它确实编译,但是,不会产生预期的结果。我在函数stringA() 中定义了字符串。这个想法是stringA() 将在修改后将函数传递给函数(即stringB()stringC()...)。 condition() 将始终返回 0,如果我们需要进行有条件的返回,这只是一个用例。

static inline int condition(void)
{
#ifdef SIM
    return 1;
#else
    return 0;
#endif
}

const char *stringA(void)
{
    return condition() ? "." : "/mnt/mmcblk0p1";
}

static inline const char *stringB(void)
{
    char buf[128];
    snprintf(buf, sizeof(buf), "%s/pathB", stringA());
    return condition() ? "" : buf;
}

void main()
{
      /* Pass 1 */
      char *str1 = strdup(stringB());
      printf("%s\n", str1); 

      /* Pass 2 */
      char *str2 = stringB();
      printf("%s\n", str2);

      /* Pass 3 */
      char str3[256];
      strcpy(str3, stringB());

      return;
}

更多问题和反馈:

1) Pass 1 不打印任何内容。为什么?

2) Pass 2 不打印任何内容。又是为什么?我认为使用strdup() 会将所有字符指针传递给str2

3) 通过 3 打印垃圾(不需要的字符)。为什么?我选择不使用指针。 strcpy() 似乎不起作用。

4) 我从return 语句中删除了condition(),但出现了段错误。为什么?

static inline const char *stringB(void)
{
    char buf[128];
    snprintf(buf, sizeof(buf), "%s/pathB", stringA());
    return buf;
}

5) 但是,下面的这种方法(我使用了参数)似乎可以打印出“/mnt/mmcblk0p1/pathB”。当我的其他尝试失败时,我不确定它是如何工作的。有什么解释吗?我不是特别喜欢这种方法,因为它需要我创建不必要的参数并在 main() 中创建一个不必要的 *buf 变量

static inline const char *stringB(char *buf, int len)
{
    snprintf(buf, len, "%s/pathB", stringA());
    return condition() ? "" : buf;
}

void main()
{
      char *buf;
      char *str1 = strdup(stringB(buf, 128));
      printf("%s\n", str1); //It prints 
      return;
}

【问题讨论】:

  • 返回一个指向局部变量的指针是一场等待发生的灾难。 (即,stringB 不应返回 buf
  • @WilliamPursell 如何解决这个问题。请指教
  • @Sedmaister 如果要堆栈分配,使用字符串的调用者需要进行分配,将其传递给被调用者进行修改。否则,无论您在调用堆栈中的哪个位置,您始终可以返回指向动态(或静态)分配的字符串的指针。
  • stringB() 引入了未定义的行为。 buf是自动存储时长,函数返回时不存在,

标签: c string pointers char


【解决方案1】:
static inline const char *stringB(void)
{
    char buf[128];
    snprintf(buf, sizeof(buf), "%s/pathB", stringA());
    return condition() ? "" : buf;
}

基本上你不想这样做...... 在这里返回 buf,返回的内存只是在堆栈上,将被其他东西重用......也许是调用函数......无论如何它不是你的记忆......你可以返回 @987654322 @ 那是一个静态字符 * 并且不能改变...... 如果你想返回一个字符串,它必须在一个传递给函数的缓冲区中,比如:

static inline const char *stringB(char *buf, size_t len)
{
    snprintf(buf, len, "%s/pathB", stringA());
    return condition() ? "" : buf;
}

返回你刚刚传入的缓冲区没有什么意义……但它是合法的……

或分配在函数中;

static inline const char *stringB(void)
{
    char * buf = malloc(128);
    snprintf(buf, 128, "%s/pathB", stringA());
    return condition() ? "" : buf;
}

【讨论】:

  • 在这种情况下,我应该担心以后释放 malloc 吗?
  • 如果你正在分配它,你应该总是返回缓冲区......并总是释放它......你永远不应该返回"",因为这会崩溃,你可以设置buf[0]='\0';如果条件,它将作为一个空字符串工作。
【解决方案2】:

随着...

static inline const char *stringB(void)
{
    char buf[128];
    ...
    return buf;
}

你正在返回一个指向局部变量的指针,一旦函数stringB 离开,它的生命周期就会结束。然后访问这个指针是未定义的行为,而您所观察到的就是这样。

只是为了尝试一下,写static char buf[128];,这样缓冲区的生命周期就会超过函数执行的生命周期。然而,这不是最好的解决方案,因为它不是线程安全的。像使用 stringB(char *buf, int len) 一样将目标传递给函数会更好(尽管您应该在所有代码路径中返回 buf)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-13
    • 2011-09-16
    • 1970-01-01
    • 2011-07-07
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多