Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

malloc error in struct (C)

Tags:

c++

c

malloc

struct

I have the following code in the C header

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

And I implemented the following code in the test program

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

And it gave me the error message: "A value of type void cannot be used to initialize an entity of type 'kiss_fft_ctx' ".

I am using Visual Studio C/C++ win32 console project.

Can anyone tell me how to correctly use the malloc here? Thanks!

like image 262
Cancan Avatar asked Aug 04 '13 19:08

Cancan


2 Answers

You need to cast the return type like this:

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

but the implication is that you're compiling your code as C++ rather than C, because that's a C++ error rather than a C error. You might want to check your file extension and/or your compiler settings.

If you really are using C++, you should at a minimum use new rather than malloc:

kiss_fft_cpx *fin = new kiss_fft_cpx[4];

and ideally rethink whether you need to be creating objects dynamically like this - could you be using a std::vector or similar instead?

like image 83
RichieHindle Avatar answered Oct 20 '22 01:10

RichieHindle


In C you can cast the void pointer returned by malloc. C does this for you but you can also be explicit.

malloc returns a void * or void pointer, this returned value can then be cast by a programmer into other pointer types. Or the programmer can rely on C to do the type conversion. C's type conversion using casts is not expected to change.

However, C code that relies on the C-compiler can be obstuse and difficult to read. A development programmer can help maintenance programmers who will eventually have to read the code.

Adding an explicit cast to the returned value of malloc helps humans who will have to read the code and determine the author's intent. This is the real benefit of explicitely casting the void pointer returned by malloc. This programming practice does NOT mis-direct the compiler or make use of some arcane compiler feature that might change.

The following three examples highlight this programming practice. In the first example, malloc (which is defined in <stdlib.h>) is explicitely cast and some trivial work is performed.

   #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

   }

In this second example, the only difference is that <stdlib.h> is commented out. The code still runs and produces the same result. Now, the "why" of why this works is fairly direct. When C does NOT find the prototype for a function it assumes that the function returns an int, but malloc returns a void pointer. In this case the explicit cast has told the C compiler, as well as the source's carbon unit, that the value returned by malloc should be converted into a character pointer.

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

   }

The final (yeah) example does NOT issue the cast and does not include <stdlib.h>. Both the Eclipse editor and the compiler complain about this code (as they should). The compiler message is

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

And the source code is:

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

   }

Changing example 3 to include results in no warnings and the program runs as intended. However, both examples 2 and 3 lack the explicit cast and over the lifetime of code written in this style such code will be more expensive and more likely to be changed incorrectly by humans (thus the additional expense) than explicit using casts which are supported by C-compilers.

like image 33
JackCColeman Avatar answered Oct 20 '22 01:10

JackCColeman