Return 这种创建二维数组的奇怪方法的函数类型
Return type of function for this odd way of creating 2D array
此问题的来源参考:
我使用了引用 post 的答案中显示的代码的改编来创建字符串数组:
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
我意识到对于非常大的数组,此方法不是最佳方法,因为在尝试分配时单个大块连续内存变得非常昂贵。但是在创建中小型阵列时,这些优势可能会很有吸引力。例如。此方法仅使用对 malloc()
的一次调用来分配一个连续的块内存,因此在使用它时只需要对 free()
进行一次调用,使其成为我所见过的更多惯用方法的理想替代方法. (多次调用 malloc()
和 free()
的用户)
所以,我想把它封装成一个函数,但至今没发现return兼容什么类型:
T CreateStringArray(int rows, int cols)
{
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
return T;
}
什么形式的 T
可以使用此函数?
您可以尝试类似的方法:
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
。因为 string
是指向 cols
元素的一维数组的指针。
分机:
关于为什么使用 cols
而不是 rows
的详细信息:
数组名在使用时是指向其第一个元素的指针。比如int arr[5]
,这里arr
就是指向a[0]
.
的指针
虽然 int a[rows][cols]
,这里 a
不是指向 a[0][0]
的指针,而是指向其 a[0]
的指针,其类型为 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]
的指针是指向 {1, 2, 3}
的指针,它是指向数组的指针3 个整数,可以写成 int (*)[3]
=> 通常它是 `int (*) [cols]'
如果我理解正确,函数应该return函数内分配的指针,
指针的类型为char (*)[cols]
,但是当声明函数时,函数的return类型对变量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 );
你会 喜欢 到 return char (*)[rows]
,但这是一个可变修改的类型,并且只有对象(不是函数)声明没有链接(与所有函数不同)在块或函数原型范围内可以具有可变修改类型 (C17 6.7.6.2/2)。
因此,您可以为函数的 return 类型做的最好的事情是 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)
后者也可以加cast,但我以不对分配函数的结果进行cast的原则省略
此问题的来源参考:
我使用了引用 post 的答案中显示的代码的改编来创建字符串数组:
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
我意识到对于非常大的数组,此方法不是最佳方法,因为在尝试分配时单个大块连续内存变得非常昂贵。但是在创建中小型阵列时,这些优势可能会很有吸引力。例如。此方法仅使用对 malloc()
的一次调用来分配一个连续的块内存,因此在使用它时只需要对 free()
进行一次调用,使其成为我所见过的更多惯用方法的理想替代方法. (多次调用 malloc()
和 free()
的用户)
所以,我想把它封装成一个函数,但至今没发现return兼容什么类型:
T CreateStringArray(int rows, int cols)
{
char (*string)[rows] = malloc(sizeof(char [rows][cols]));
memset(string, 0, sizeof(char [rows][cols]));
return T;
}
什么形式的 T
可以使用此函数?
您可以尝试类似的方法:
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
。因为 string
是指向 cols
元素的一维数组的指针。
分机:
关于为什么使用 cols
而不是 rows
的详细信息:
数组名在使用时是指向其第一个元素的指针。比如int arr[5]
,这里arr
就是指向a[0]
.
虽然 int a[rows][cols]
,这里 a
不是指向 a[0][0]
的指针,而是指向其 a[0]
的指针,其类型为 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]
的指针是指向 {1, 2, 3}
的指针,它是指向数组的指针3 个整数,可以写成 int (*)[3]
=> 通常它是 `int (*) [cols]'
如果我理解正确,函数应该return函数内分配的指针,
指针的类型为char (*)[cols]
,但是当声明函数时,函数的return类型对变量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 );
你会 喜欢 到 return char (*)[rows]
,但这是一个可变修改的类型,并且只有对象(不是函数)声明没有链接(与所有函数不同)在块或函数原型范围内可以具有可变修改类型 (C17 6.7.6.2/2)。
因此,您可以为函数的 return 类型做的最好的事情是 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)
后者也可以加cast,但我以不对分配函数的结果进行cast的原则省略