0

我有两个要编译成可执行文件的 .c 文件。刚刚开始学习 C,我发现知道如何在函数之间传输文本作为参数很棘手(我发现在其他所有语言中都非常简单)。

这是两个文件:

程序.c

#include <stdio.h>
#include <string.h>

int main(){

char temp[40] = stringCall();
printf("%s",temp);

}

字符串返回.c

#include <stdio.h>
#include <string.h>

char[] stringCall(){

char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;

}

我通常会遇到类似“Segmentation Failed (core dumped)”之类的问题。我已经做了很多谷歌搜索,令人惊讶的是我真的找不到解决方案,当然也没有简单的教程“这是如何在函数之间移动文本”。

任何帮助,将不胜感激 :)

4

2 回答 2

2
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;

这是无效的,您将返回一个自动数组,该数组在函数返回后超出范围 - 这会调用未定义的行为。尝试返回字符串文字本身(它在整个程序中都有效):

return "Hello, Stack Overflow!";

或者您的数组的动态副本:

char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);

在后一种情况下,您需要free()调用函数中的字符串。

于 2012-09-19T17:01:09.483 回答
1

你是对的,这在 C 中并不简单,因为 C 不能将字符串视为值。

最灵活的方法是:

// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
    puts(temp);
} else {
    // error-handling
    puts("My buffer wasn't big enough");
}

// StringReturn.c
int stringCall(char *buf, int size) {
    const char toReturn[] = "Hello, Stack Overflow!";
    if (sizeof toReturn <= size) {
        strcpy(buf, toReturn);
    }
    return sizeof toReturn;
}
  • stringCall不返回字符串数据,而是将其写入调用者提供的缓冲区
  • 缓冲区总是带有大小。您可以为此使用size_tor而不是.ssize_tint
  • stringCall在写入之前检查大小。还有其他方法可以在单个调用中执行此操作,所有这些方法要么不在 C89 和 C99 中,要么以其他方式存在缺陷。C11 介绍strcpy_s。使用您可以使用的工具,这在逻辑上应该等同于您自己检查它,就像我上面的代码一样。永远不要忘记确保 nul 终止符有空间,它无形地潜伏在每个 C 字符串的末尾。
  • stringCall返回它想要写入的字节数,即使它不写任何东西。这意味着缓冲区太小的调用者可以分配一个更大的缓冲区并重试。为此,调用者可以stringCall(NULL, 0)在不尝试任何特定缓冲区的情况下获取大小。
  • 我在sizeof这里使用是因为我使用的是编译器知道其大小的数组,但实际上stringCall可能会使用strlen或其他方式来了解它想要写入多少数据。
  • 正如我所写,要求调用者不要为size. 这通常没问题,因为事实上他们的缓冲区不能有负大小,所以如果他们这样做,他们的代码已经有问题了。但是,如果您想真正确定,或者如果您想帮助您的调用者捕获这些错误,您可以编写if ((int) sizeof toReturn < size)if (size > 0 && sizeof toReturn < size).

“最灵活”并不总是最好的,但是当函数实际上是动态生成文本时,这很好,特别是当调用者没有简单的方法提前知道长度而不做一半的工作时stringCall应该为他们做的。该接口类似于C99标准功能snprintf

于 2012-09-19T17:18:14.230 回答