【问题标题】:malloc error in struct (C)结构 (C) 中的 malloc 错误
【发布时间】:2013-08-04 19:38:52
【问题描述】:

我在 C 头文件中有以下代码

typedef struct {
    kiss_fft_scalar r;
    kiss_fft_scalar i;
} kiss_fft_cpx;

我在测试程序中实现了以下代码

kiss_fft_cpx *fin = malloc(4*sizeof(kiss_fft_cpx));

它给了我错误消息:“void 类型的值不能用于初始化 'kiss_fft_ctx' 类型的实体”。

我正在使用 Visual Studio C/C++ win32 控制台项目。

谁能告诉我如何在这里正确使用 malloc?谢谢!

【问题讨论】:

标签: c++ c struct malloc


【解决方案1】:

您需要像这样转换返回类型:

kiss_fft_cpx *fin = (kiss_fft_cpx*) malloc(4*sizeof(kiss_fft_cpx));

但这意味着您将代码编译为 C++ 而不是 C,因为这是 C++ 错误而不是 C 错误。您可能需要检查文件扩展名和/或编译器设置。

如果你真的使用 C++,你至少应该使用new 而不是malloc

kiss_fft_cpx *fin = new kiss_fft_cpx[4];

最好重新考虑您是否需要像这样动态创建对象 - 您可以使用 std::vector 或类似名称吗?

【讨论】:

  • 酷,问题是我必须在我的 c++ 项目中使用别人编写的 C 代码。所以,我想知道是否也可以使用其他方案而不是 malloc 来完成内存分配。(否则,当我们在 C++ 中使用 C 时,C++ 在这里似乎很愚蠢)
  • @Cancan 是,但你最好不要。只需编译为 C 即可。 永远不要尝试将 C 代码编译为 C++。 它们是不同的语言。
  • 另外,@RichieHindle:“你需要像这样转换返回类型” - 不,那是错误的 - 他需要更改编译器。
  • @Cancan 是的,完全正确。没有其他东西真的有意义。
  • @Cancan:这取决于您如何使用对象和容器。如果需要在 C 中操作容器,则不能使用 C++ 容器。但是,如果您只需要将指向对象本身的指针从 C++ 传递到 C,那么它们位于哪个容器中并不重要。您甚至可以使用 @987654327 将 C++ 中的 std::vector 作为普通旧数组传递到 C @(或在 C++11 中使用 data())只要 C 代码不尝试修改数组即可。
【解决方案2】:

在 C 中,您可以转换 malloc 返回的 void 指针。 C 会为您执行此操作,但您也可以是显式的。

malloc 返回一个 void * 或 void 指针,然后程序员可以将这个返回值转换为其他指针类型。或者程序员可以依靠 C 来进行类型转换。 C 使用强制类型转换的类型转换预计不会改变。

但是,依赖于 C 编译器的 C 代码可能晦涩难懂且难以阅读。 开发程序员可以帮助最终必须阅读代码的维护程序员。

malloc 的返回值添加显式强制转换有助于那些将拥有 阅读代码并确定作者的意图。这是显式转换 malloc 返回的 void 指针的真正好处。这种编程实践确实 不要误导编译器或使用一些可能会改变的神秘编译器功能。

以下三个示例突出了这种编程实践。在第一个例子中, malloc(在<stdlib.h> 中定义)被明确地强制转换并且一些琐碎的工作是 执行。

   #include <stdlib.h>
   #define nr_chars 4
   main()
   {
    char *data;

    data = (char *) malloc(nr_chars*sizeof(char));

    *data++ = 'a';
    *data++ = 'b';
    *data++ = 'c';
    *data++ = '\0';    // it is allowed to go one past an array

    data -= nr_chars;  // back to the front of data

    printf("%s\n", data);
    // prints abc at the console

   }

在第二个示例中,唯一的区别是 &lt;stdlib.h&gt; 被注释掉了。这 代码仍然运行并产生相同的结果。现在,为什么这个工作的“为什么”是相当直接的。当 C 没有找到函数的原型时,它假定该函数返回一个 int,但 malloc 返回一个 void 指针。在这种情况下,显式转换已告知 C 编译器以及源代码的碳单元,malloc 返回的值应转换为字符指针。

   //#include <stdlib.h>
   #define nr_chars 4
   main()
   {
   char *data;

   data = (char *) malloc(nr_chars*sizeof(char));

   *data++ = 'a';
   *data++ = 'b';
   *data++ = 'c';
   *data++ = '\0';    // it is allowed to go one past an array

   data -= nr_chars;  // back to the front of data

   printf("%s\n", data);
   // prints abc at the console

   }

最后的(是的)示例不发出演员表,也不包括&lt;stdlib.h&gt;。 Eclipse 编辑器和编译器都抱怨这个代码(他们应该这样做)。编译器消息是

   ..\main.c(18) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int'

而源代码是:

   //#include <stdlib.h>
   #define nr_chars 4
   main()
   {
   char *data;

   data = malloc(nr_chars*sizeof(char));

   *data++ = 'a';
   *data++ = 'b';
   *data++ = 'c';
   *data++ = '\0';    // it is allowed to go one past an array

   data -= nr_chars;  // back to the front of data

   printf("%s\n", data);
   // compiler displays a "warning" and prints abc at the console

   }

将示例 3 更改为包含将导致没有警告并且程序按预期运行。但是,示例 2 和示例 3 都缺少显式强制转换,并且在以这种风格编写的代码的整个生命周期中,与显式使用支持的强制转换相比,这样的代码将更昂贵并且更容易被人错误地更改(因此产生额外费用) C 编译器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 2012-10-02
    • 2014-08-12
    • 2012-01-19
    • 2011-02-12
    相关资源
    最近更新 更多