[英]Function that returns an array of strings C
Is there a way to return an array of strings from a function without using dynamic memory allocation? 有没有一种方法可以在不使用动态内存分配的情况下从函数返回字符串数组? The function goes something like this: 该函数是这样的:
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;
}
In C, an object has one of four storage durations (also called lifetimes): static, thread, automatic, and allocated (C 2018 6.2.4 1). 在C中,对象具有四个存储期限(也称为生存期)之一:静态,线程,自动和已分配(C 2018 6.2.4 1)。
Objects with automatic duration are automatically created inside a function and cease to exist when execution of the function ends, so you cannot use these that is created inside your function to return a value. 具有自动持续时间的对象会在函数内部自动创建,并且在函数执行结束时将不复存在,因此您不能使用在函数内部创建的对象返回值。
Objects with allocated storage duration persist until freed, but you have asked to exclude those. 分配了存储时间的对象将一直保留到释放为止,但是您已要求排除这些对象。
Thread storage duration is either likely not applicable to your situation or is effectively equivalent to static storage duration, which I will discuss below. 线程存储持续时间可能不适用于您的情况,或者实际上等效于静态存储持续时间,我将在下面讨论。
This means your options are: 这意味着您可以选择:
Thus, a typical solution looks like this: 因此,典型的解决方案如下所示:
size_t HowMuchSpaceIsNeeded(char original[1000][1000])
{
… Calculate size.
return SizeNeeded;
}
void modify(char destination[][1000], char original[1000][1000])
{
… Put results in destination.
}
A variation for safety is: 安全性的一种变化是:
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.
}
Then the caller does something like: 然后,调用者将执行以下操作:
size_t size = HowMuchSpaceIsNeeded(original);
char (*results)[1000] = malloc(size);
if (!results)
… Report error.
modify(results, size, original)
… Work with results.
free(results);
As Davistor notes , a function can return an array embedded in a structure. 如Davistor 注意到 ,函数可以返回嵌入在结构的阵列。 In terms of C semantics, this avoids the object lifetime problem by returning a value, not an object. 就C语义而言,这通过返回值而不是对象避免了对象生存期问题。 (The entire contents of the structure is the value of the structure.) In terms of actual hardware implementation, it is largely equivalent to the caller-passes-an-object method above. (该结构的全部内容就是该结构的值。)就实际的硬件实现而言,它在很大程度上等同于上面的调用者通过对象方法。 (The reasoning here is based on the logic of how computers work, not on the C specification: In order for a function to return a value that requires a lot of space to represent, the caller must provide the required space to the called function.) Generally, the caller will allocate space on the stack and provide that to the called function. (这里的推理是基于计算机工作原理的逻辑,而不是基于C规范:为了使函数返回需要大量空间来表示的值,调用者必须向被调用函数提供所需的空间。 )通常,调用方将在堆栈上分配空间并将其提供给被调用的函数。 This may be faster than a malloc
, but it may also use a considerable amount of stack space. 这可能比malloc
快,但它也可能占用大量堆栈空间。 Usually, we avoid using sizable amounts of stack space, to avoid overflowing the stack. 通常,我们避免使用大量堆栈空间,以避免堆栈溢出。
Although you cannot return an array type in C, you can return a struct
containing one: 尽管您不能在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;
}
I would generally recommend that you use Eric Postpischil's solution, however. 我通常建议您使用Eric Postpischil的解决方案。 One way this might not be efficient is if you need to write to a specific variable or location. 一种可能效率不高的方法是,如果您需要写入特定的变量或位置。 In that case, you could pass in its address, but here, you would need to create a large temporary array and copy it. 在这种情况下,您可以传递其地址,但是在这里,您需要创建一个大型的临时数组并将其复制。
You can't return pointers to the local variables, because lifetime of the memory to which they point is limited to the scope. 您不能返回指向局部变量的指针,因为它们所指向的内存的生存期仅限于范围。
Basically result
is a pointer to the stack-allocated array first element, so returning it and dereferencing it later will result in undefined behavior. 基本上, result
是指向堆栈分配的数组第一个元素的指针,因此,将其返回并稍后对其取消引用将导致未定义的行为。
To bypass this issue, there are few work-arounds. 要绕过此问题,很少有解决方法。
One of those, I saw in couple of projects, but I don't recommend it, because it is unsafe. 我在几个项目中看到了其中一个,但是我不建议这样做,因为它不安全。
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;
}
Another approach will be to receive result
pointer as function argument, so the caller will allocate storage for it. 另一种方法是将result
指针作为函数参数接收,因此调用方将为其分配存储空间。
void modify(char original[1000][1000], char (*result)[1000]){
result[0][1] = 42;
//...
}
void main() {
char result[1000][1000];
modify(someOriginal, result);
}
Anyway, I recommend you to read some decent book about C language and how a computer memory works. 无论如何,我建议您阅读一些有关C语言以及计算机内存如何工作的体面的书。
You cannot return a pointer to memory allocated inside a function without dynamic allocation. 如果没有动态分配,则不能返回指向函数内部分配的内存的指针。 In your case, you will allocate result[1000][1000]
on the stack in a zone which will be deallocated once the function returns. 在您的情况下,您将在堆栈中的区域中分配result[1000][1000]
,一旦函数返回,该区域将被释放。 Besides dynamic allocation, you have the option of passing a buffer as an argument to your function: 除了动态分配,您还可以选择将缓冲区作为参数传递给函数:
void modify(char original[1000][1000], char result[][]) { ... }
Now the result
matrix has to be allocated outside the modify
function and its lifetime will not depend on the function's lifetime. 现在,必须将result
矩阵分配到modify
函数之外,并且其生存期将不取决于函数的生存期。 Basically you pass the function an already allocated matrix where the result will be written. 基本上,您向函数传递一个已经分配的矩阵,该矩阵将在其中写入结果。
您可以使用从第一个字符串开始到最后一个字符串结束的链表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.