简体   繁体   English

是否可以将 void * 转换为 char **?

[英]Is it possible to cast a void * to a char **?

I have made this little code:我做了这个小代码:

void  *toto = malloc(8 * sizeof(char *) * 8);
char  **tata = (char **)toto;
tata[5][5] = 'a'

But I have a segmentation fault .但我有一个分段错误 How can I convert my void * to a char ** ?如何将我的void *转换为char **

The malloc call is allocating space for 64 pointers of uninitialized memory. malloc调用正在为 64 个未初始化内存指针分配空间。 Then, you are using tata as a double indirection pointer.然后,您使用tata作为双间接指针。 That's it:就是这样:

  • tata points to the start of the 64 pointers. tata指向 64 个指针的开始。
  • tata[5] is the sixth element of the malloc d block, and since tata has type char** , tata[5] has type char* : a pointer with garbage. tata[5]malloc d 块的第六个元素,由于tata类型为char**tata[5]类型为char* :带有垃圾的指针。
  • tata[5][5] is the sixth element pointed from the start of tata[5] . tata[5][5]是从tata[5]开始指向的第六个元素。 But since tata[5] is garbage, tata[5][5] is a random element in your memory space.但是由于tata[5]是垃圾,因此tata[5][5]是您内存空间中的随机元素。

Yes, it is definitely possible.是的,这绝对是可能的。 But you'll have to do more.但你必须做得更多。

You have an array of void s named toto :您有一个名为totovoid数组:

void *toto = malloc(8 * sizeof(char *) * 8);

In other words - toto is a pointer to a piece of memory containing 8 * sizeof(char *) * 8 voids - you've probably thought that because computation suggests it is an array of pointers, the compiler will figure it itself.换句话说 - toto是一个指向包含8 * sizeof(char *) * 8 toto值的内存的指针 - 你可能认为因为计算表明它是一个指针数组,编译器会自己计算出来。 It won't - what a compiler sees is something like this:它不会 - 编译器看到的是这样的:

void *toto = malloc(64);

therefore you'll end up with a 1-dimensional "flat" array where each element is a void .因此,您最终会得到一个一维“平面”数组,其中每个元素都是一个void

Now you cast it:现在你施放它:

char  **tata = (char **)toto;

and it's all good so far.到目前为止一切都很好。 Now you have tata which points to an array of pointers to char arrays which is not initialized .现在你有tata它指向一个指向未初始化的char 数组的指针数组。 The type of tata[5] is *char . tata[5]的类型是*char

So when you do:所以当你这样做时:

tata[5][5] = 'a';

you're:你是:

  1. accessing that array of pointers ( tata ) - ok访问该指针数组( tata ) - 好的
  2. accessing 6th (indexing from 0) pointer tata[5] - ok访问第 6 个(从 0 开始索引)指针tata[5] - 好的
  3. but tata[5] is not initialized and contains either NULL or some garbagetata[5]未初始化并且包含 NULL 或一些垃圾
  4. acessing 6th element of *tata[5] - SEGFAULT , because it's not valid pointer访问*tata[5] - SEGFAULT第 6 个元素,因为它不是有效的指针

What you must do is:你必须做的是:

  • initialize toto to how many "rows" you need in resulting matrixtoto初始化为结果矩阵中需要的“行”数
  • manually create all those end arrays yourself自己手动创建所有这些末端阵列

So it could look like this:所以它看起来像这样:

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 */

Which would compile and run without SEGFAULT.它可以在没有 SEGFAULT 的情况下编译和运行。

I also suggest doing the cast before malloc and using constants for numbers of rows and columns, which will give us this:我还建议在 malloc 之前进行强制转换并使用常量来表示行数和列数,这将为我们提供:

int num_rows = 8;
int num_cols = 8;
char **tata = (char**)malloc(num_rows * sizeof(char*));
int i;
for (i = 0; i < num_rows; i++) {
  tata[i] = (char*)malloc(num_cols * sizeof(char));
}
tata[5][5] = 'a';

It is possible to cast void * to any pointer type.可以将void *为任何指针类型。 Indeed, if it weren't you couldn't use malloc to allocate very well, since its return value is of type void * .事实上,如果不是这样,你就不能很好地使用malloc进行分配,因为它的返回值是void *类型。

Of course the area of memory pointed to by the void * must still be valid for its use, ie, large enough and aligned correctly.当然, void *指向的内存区域必须仍然对其使用有效,即足够大且正确对齐。 (In case of malloc the returned memory is correctly aligned for “any use”, at least as far a standard C is concerned.) (在malloc的情况下,返回的内存正确对齐以供“任何用途”使用,至少就标准 C 而言。)

The bug in your code is here:您代码中的错误在这里:

tata[5][5] = 'a'

You are dereferencing the 6th pointer to char * counting from the start of malloc ed block, which is uninitialised.您正在取消引用从malloc ed 块开始计数的第 6 个指向char *指针,该指针未初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM