【问题标题】:Is it possible to cast a void * to a char **?是否可以将 void * 转换为 char **?
【发布时间】:2014-03-26 09:39:05
【问题描述】:

我做了这个小代码:

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

但我有一个分段错误。如何将我的 void * 转换为 char **

【问题讨论】:

  • 您为什么以及要达到什么目标?
  • 这只是一个测试。没有原因,没有其他代码。
  • 当然可以。你在做。您只是使用未初始化的值进行操作,因此最好的情况是崩溃。
  • @JérémyPouyet 也会崩溃,你为什么不使用调试器看看值是什么
  • @Jérémy, char** - 这意味着 tata 是指向 char 指针的指针。不是二维数组!因此,当您将 toto 类型转换为它时 - toto 必须是指向位置的指针,其中存储了指向 char 的指针。

标签: c pointers void


【解决方案1】:

malloc 调用正在为 未初始化 内存的 64 个指针分配空间。然后,您使用tata 作为双间接指针。就是这样:

  • tata 指向 64 个指针的开头。
  • tata[5]mallocd 块的第六个元素,由于tata 的类型为char**tata[5] 的类型为char*:带有垃圾的指针。
  • tata[5][5] 是从tata[5] 开始指向的第六个元素。但由于tata[5] 是垃圾,tata[5][5] 是你内存空间中的随机元素。

【讨论】:

    【解决方案2】:

    是的,这绝对是可能的。但是你必须做更多的事情。

    您有一个名为 totovoids 数组:

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

    换句话说 - toto 是一个指向包含 8 * sizeof(char *) * 8 voids 的内存的指针 - 你可能认为因为计算 suggests 它是一个指针数组,编译器将自己想办法。 它不会 - 编译器 看到 是这样的:

    void *toto = malloc(64);
    

    因此,您最终会得到一个一维“平面”数组,其中每个元素都是一个 void

    现在你投射它:

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

    到目前为止一切都很好。现在你有了tata,它指向一个指向未初始化的char数组的指针数组。 tata[5] 的类型是*char

    所以当你这样做时:

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

    你是:

    1. 访问该指针数组 (tata) - 好的
    2. 访问第 6 个(从 0 开始索引)指针 tata[5] - 好的
    3. tata[5] 未初始化并且包含 NULL 或一些垃圾
    4. 正在访问 *tata[5] - SEGFAULT 的第 6 个元素,因为它不是有效的指针

    你必须做的是:

    • toto初始化为生成矩阵需要多少“行”
    • 自己手动创建所有这些末端数组

    所以它可能看起来像这样:

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

    无需 SEGFAULT 即可编译和运行。

    我还建议在 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';
    

    【讨论】:

      【解决方案3】:

      可以将void * 转换为任何指针类型。确实,如果不是这样,您将无法使用malloc 很好地分配,因为它的返回值是void * 类型。

      当然,void * 指向的内存区域必须仍然对其使用有效,即足够大并且正确对齐。 (在malloc 的情况下,返回的内存为“任何用途”正确对齐,至少就标准C 而言。)

      您的代码中的错误在这里:

      tata[5][5] = 'a'
      

      您正在取消引用第 6 个指向 char * 的指针,该指针从未初始化的 malloced 块的开头开始计数。

      【讨论】:

        猜你喜欢
        • 2012-03-26
        • 2020-10-24
        • 2011-02-24
        • 1970-01-01
        • 1970-01-01
        • 2011-06-17
        • 2015-12-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多