是否可以在不使用动态内存分配的情况下从函数返回字符串数组?该函数是这样的:
char** modify(char original[1000][1000]){
char result[1000][1000];
// some operations are applied to the original
// the original is copied to the result
return result;
}
答案 0 :(得分:2)
在C中,对象具有以下四个存储期限之一(也称为生存期):静态,线程,自动和分配的存储期限(C 2018 6.2.4 1)。
具有自动持续时间的对象是在函数内部自动创建的,并且在函数执行结束时不再存在,因此您不能使用在函数内部创建的对象返回值。
分配了存储时间的对象会一直保留到释放为止,但是您已要求排除这些对象。
线程存储持续时间可能不适用于您的情况,或者实际上等效于静态存储持续时间,我将在下面讨论。
这意味着您的选择是:
因此,典型的解决方案如下所示:
size_t HowMuchSpaceIsNeeded(char original[1000][1000])
{
… Calculate size.
return SizeNeeded;
}
void modify(char destination[][1000], char original[1000][1000])
{
… Put results in destination.
}
安全性的一种变化是:
void modify(char destination[][1000], size_t size, char original[1000][1000])
{
if (size < amount needed)
… Report error (possibly by return value, or program abort).
… Put results in destination.
}
然后,呼叫者会执行以下操作:
size_t size = HowMuchSpaceIsNeeded(original);
char (*results)[1000] = malloc(size);
if (!results)
… Report error.
modify(results, size, original)
… Work with results.
free(results);
与Davistor notes一样,函数可以返回嵌入在结构中的数组。就C语义而言,这通过返回值而不是对象避免了对象生存期问题。 (该结构的全部内容就是该结构的值。)就实际的硬件实现而言,它在很大程度上等同于上面的调用者通过对象方法。 (这里的推理是基于计算机工作原理的逻辑,而不是基于C规范:为了使函数返回需要大量空间来表示的值,调用者必须向被调用函数提供所需的空间。 )通常,调用方将在堆栈上分配空间并将其提供给被调用的函数。这可能比malloc
快,但是它也可能占用大量堆栈空间。通常,我们避免使用大量堆栈空间,以避免堆栈溢出。
答案 1 :(得分:1)
尽管您无法在C语言中返回数组类型,但可以返回包含以下内容的struct
:
#include <string.h>
#define NSTRINGS 100
#define STR_LEN 100
typedef struct stringtable {
char table[NSTRINGS][STR_LEN];
} stringtable;
stringtable modify ( const stringtable* const input )
{
stringtable result;
memcpy( &result, input, sizeof(result) );
return result;
}
但是,我通常建议您使用Eric Postpischil的解决方案。一种可能效率不高的方法是,如果您需要写入特定的变量或位置。在这种情况下,您可以传递其地址,但是在这里,您需要创建一个大型的临时数组并将其复制。
答案 2 :(得分:0)
您不能将指针返回到局部变量,因为它们所指向的内存的生存期仅限于范围。
result
基本上是指向堆栈分配的数组第一个元素的指针,因此将其返回并稍后对其取消引用将导致未定义的行为。
要绕过此问题,很少有解决方法。
我在几个项目中看到了其中一个,但是我不建议这样做,因为它不安全。
char** modify(char original[1000][1000]){
// `result` is static array, which lifetime is equal to the lifetime of the program
// Calling modify more than one time will result in overwriting of the `result`.
static char result[1000][1000];
return result;
}
另一种方法是接收result
指针作为函数参数,因此调用方将为其分配存储空间。
void modify(char original[1000][1000], char (*result)[1000]){
result[0][1] = 42;
//...
}
void main() {
char result[1000][1000];
modify(someOriginal, result);
}
无论如何,我建议您阅读一些有关C语言以及计算机内存如何工作的不错的书。
答案 3 :(得分:0)
如果没有动态分配,则不能将指针返回到在函数内部分配的内存。在您的情况下,您将在堆栈中的result[1000][1000]
上分配一个区域,一旦函数返回,该区域将被释放。除了动态分配,您还可以选择将缓冲区作为参数传递给函数:
void modify(char original[1000][1000], char result[][]) { ... }
现在必须将result
矩阵分配到modify
函数之外,并且其生存期将不取决于函数的生存期。基本上,您向函数传递一个已经分配的矩阵,该矩阵将在其中写入结果。
答案 4 :(得分:-3)
您可以使用从第一个字符串开始到最后一个字符串结束的链表。