我已经制作了这个小代码:
void *toto = malloc(8 * sizeof(char *) * 8);
char **tata = (char **)toto;
tata[5][5] = 'a'
但我有一个分段错误。如何将void *
转换为char **
?
答案 0 :(得分:5)
malloc
调用为64个未初始化内存指针分配空间。然后,您使用tata
作为双间接指针。就是这样:
tata
指向64个指针的开头。tata[5]
是malloc
d块的第六个元素,由于tata
的类型为char**
,tata[5]
的类型为char*
:带垃圾的指针。tata[5][5]
是从tata[5]
开头指向的第六个元素。但由于tata[5]
是垃圾,tata[5][5]
是您的内存空间中的随机元素。答案 1 :(得分:3)
是的,这绝对是可能的。但你必须做更多。
您有一个名为void
的{{1}}数组:
toto
换句话说 - void *toto = malloc(8 * sizeof(char *) * 8);
是指向包含toto
个空洞的内存的指针 - 您可能认为因为计算建议它是一个指针数组,编译器会自己解决它。
它不会 - 编译器看到的是这样的:
8 * sizeof(char *) * 8
因此,您最终会得到一个“平面”数组,其中每个元素都是void *toto = malloc(64);
。
现在你施展它:
void
到目前为止,这一切都很好。现在你有char **tata = (char **)toto;
指向char数组的指针数组,未初始化。 tata
的类型为tata[5]
。
所以当你这样做时:
*char
你:
tata[5][5] = 'a';
) - 确定tata
- 确定tata[5]
未初始化并且包含NULL或一些垃圾tata[5]
- *tata[5]
的第6个元素,因为它不是有效指针你必须做的是:
SEGFAULT
初始化为矩阵所需的“行数” 所以看起来像这样:
toto
在没有SEGFAULT的情况下编译和运行。
我还建议在malloc之前进行强制转换,并使用常量来表示行数和列数,这样就可以了:
void *toto = malloc(8 * sizeof(char *)); /* assuming 8 rows */
char **tata = (char **)toto;
int i;
for (i = 0; i < 8; i++) {
tata[i] = (char*)malloc(8 * sizeof(char)); /* assuming 8 columns */
}
tata[5][5] = 'a'; /* all is well now */
答案 2 :(得分:0)
可以将void *
转换为任何指针类型。实际上,如果它不能很好地使用malloc
进行分配,因为它的返回值是void *
类型。
当然void *
指向的内存区域仍然必须对其使用有效,即足够大并且正确对齐。 (如果malloc
返回的内存已正确对齐“任何用途”,至少就标准C而言。)
您的代码中存在错误:
tata[5][5] = 'a'
您正在取消引用char *
的第6个指针,从malloc
ed块的开头开始计算,该块未经初始化。