这个问题的来源参考:分配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 );