c-为创建2D数组的这种奇怪方式返回函数类型



这个问题的来源参考:分配2D阵列的奇怪方法

我使用了引用文章答案中所示代码的改编来创建字符串数组:

char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));

我意识到,对于超大的数组,这种方法不是最佳的,因为在尝试分配时,单个大块的连续内存会变得非常昂贵。但是,当创建中小型阵列时,其优势可能很有吸引力。例如,该方法只使用对malloc()的一次调用来分配单个连续块内存,因此在使用它时只需要对free()进行一次调用,这使它成为我见过的更惯用的方法的理想替代方案。(使用对malloc()free()的多次调用的那些,)

所以,我想把它封装到一个函数中,但到目前为止,我还没有发现什么返回类型是兼容的:

T  CreateStringArray(int rows, int cols)
{
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
return T;
}

什么形式的T可以使用此功能?

您会希望返回char (*)[rows],但这是一个可变修改的类型,只有在块或函数原型范围内声明没有链接(与所有函数不同)的对象(而不是函数)才能具有可变修改的类型(C17 6.7.6.2/2)。

因此,函数的返回类型最好是char *void *

然而,你可以用一个宏来修补它:

void *CreateStringArray_func(int rows, int cols)
{
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
return string;
}
#define CreateStringArray(rows, cols) 
((char (*)[rows]) CreateStringArray_func(rows, cols))

但在这种特殊情况下,我可能只会使用

#define CreateStringArray(rows, cols) calloc(rows, cols)

您也可以将强制转换添加到后者,但出于不强制转换分配函数结果的原则,我省略了它。

你可以尝试这样的东西:

void * CreateStringArray(int rows, int cols)
{
char (*string)[cols] = malloc(sizeof(char [rows][cols]));
memset((void*)string, 0, sizeof(char [rows][cols]));
return string;
}
int main()
{
char (*p)[4] = (char (*)[4])CreateStringArray(3, 4);
}

注意,char (*string)[cols]应定义为cols,而不是rows。因为CCD_ 12是指向CCD_。

扩展:

关于为什么使用cols而不是rows:的详细信息

数组名称在使用时是指向其第一个元素的指针。例如int arr[5],这里arr是指向a[0]的指针。

尽管int a[rows][cols],这里a不是a[0][0]的指针,而是指向其a[0]的指针,CCD_22具有类型int (*)[cols]

要理解这一点,你必须思考C是如何在内存中存储多维数组的?它实际上是以一维数组的形式逐行存储的。

例如int a[2][3] = {{1, 2, 3}, {4, 5, 6}};被存储为1 2 3 4 5 6,这里a[0]{1, 2, 3},所以指向a[0]的指针是指向可被写为int (*)[3]=>一般来说是`int(*)[cols]'

如果我理解正确,函数应该返回函数中分配的指针

指针的类型为char (*)[cols],但当声明函数时,函数的返回类型对变量cols一无所知。

在这种情况下,应该像一样声明函数

void * CreateStringArray(int rows, int cols) )
{
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
return string;
}

在呼叫者中,你可以写

char ( *string )[cols] = CreateStringArray( rows, cols );

相关内容

  • 没有找到相关文章

最新更新