2

I have this C++ code:

#include <stdlib.h>
int main(){
    char *Teclas;
    Teclas = calloc(1024,sizeof(char));
}

And the compiler is giving the following error:

error: invalid conversion from `void*' to `char*'

What does this error mean and how do I fix it?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
user2792662
  • 77
  • 1
  • 1
  • 3

6 Answers6

16

The problem is that you're trying to compile C with a C++ compiler. As the error message says, this line:

Teclas = calloc(1024,sizeof(char));

tries to convert the untyped void* pointer returned by calloc into a typed char* pointer to assign to the variable of that type. Such a conversion is valid in C, but not C++.

The solution is to use a C compiler. It looks like you're using GCC, so just rename the source file to something.c, and build with gcc rather than g++.

If you really must use a compiler for the wrong language, and don't feel like rewriting this in idiomatic C++, then you'll need a cast to force it through the compiler:

Teclas = static_cast<char*>(calloc(1024,sizeof(char)));

or, if you want the code to remain valid C:

Teclas = (char*)calloc(1024,sizeof(char));

But don't do that: use the right compiler for the language. Unless this is the first stage in converting the program to C++; in which case, the next thing to do is get rid of these allocations and use std::string instead.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

calloc() returns a void*. You need to cast its value to whatever type Teclas is, which appears to be a char*. So Teclas = (char*)calloc(...).

Andy
  • 773
  • 2
  • 6
  • 22
1
void int main(int argc,char *argv[])

uhm... perhaps just int main(int argc, char *argv[])...

Apart from that: this looks like C code. Nothing in these lines suggests that you use C++. The error you are seeing is the result of you treating C code as if it was C++, whereas it isn't, because C is not C++, C++ is not C, and neither is the subset of the other one.


Compile your C code with a C compiler.

  • The `c++` tag suggests he uses C++. This code uses no features that aren't available in both C and C++, so it really doesn't matter that neither is a strict subset of the other. The commonly used parts of C are in fact a subset of C++. – Ben Voigt Sep 18 '13 at 18:26
  • 1
    @BenVoigt: "no features that aren't available in both C and C++" - apart from the implicit `void*` to `char*` conversion. This code is C, and there's no point trying to force it through the wrong compiler. – Mike Seymour Sep 18 '13 at 18:28
  • 1
    @BenVoigt "The `c++` tag suggests he uses C++" - no, it rather suggests that OP assumes that he is using C++. He's wrong (as many other people who think C is a subset of C++), and he doesn't, the code is C and not C++ and therefore it shall not be treated as such. This is not nitpicking, this is a real problem (as the question just pointed it out). –  Sep 18 '13 at 18:30
  • @H2CO3: The error message confirms that he is using C++. Yes, he got his code from a C source, and will need to fix the trivial incompatibilities before it is usable in a C++ program. But that doesn't mean he is not using C++. – Ben Voigt Sep 18 '13 at 18:37
  • @MikeSeymour: It's much easier to fix a handful of implicit `void*` conversions than add `extern "C"` everywhere, so I strongly disagree that "there's no point trying to force it through the wrong compiler". Besides, getting it to compile with a C++ compiler is often only the first step in modernizing code, where later steps actually will use C++ features. And I wouldn't call `void*` implicit conversion a *feature*, since it doesn't add value or change code organization. It's a trivial difference in the conversion rules, with a trivial fix. – Ben Voigt Sep 18 '13 at 18:39
  • 1
    @BenVoigt: OK, if this code *is* supposed to be converted to C++, then bodging it through the compiler is a reasonable first step. But I see little evidence that it's supposed to be C++ (beyond the tag and the use of the wrong compiler); and if not, the right answer is to use the right compiler. – Mike Seymour Sep 18 '13 at 18:47
0

The best solution is to just compile your code with a C compiler, as this is C code. You really shouldn't compile C code as if it were C++. However, to directly answer your question, you can force the C++ compiler to compile your C code (which is very bad!!!!).

In C++, whenever you use any function of the alloc family, you must cast the return value to the type of your lvalue. So, in this case:

Teclas = (char*)calloc(1024, sizeof(char));

The way in which I would do the above is like this:

Teclas = (char*)malloc(1024 * sizeof(*Teclas));

The benefits here: If you change the type of Teclas, you will still end up with the correct allocation size. Also, I just prefer using malloc in general.

Additionally, you have major issues throughout your code. For one thing, void int main(...)???? And you never initialize the contents of Teclas before you print it, but you free it and calloc it again for some reason. I think you meant to make that a do while loop, but there is no do.

Also, void KeyLogger(); is WRONG. That is how you declare the function, but since it is a declaration, it should be outside of main.

C0deH4cker
  • 3,959
  • 1
  • 24
  • 35
  • @H2CO3 Care to explain? – C0deH4cker Sep 18 '13 at 18:20
  • of course, [here you are](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858). –  Sep 18 '13 at 18:22
  • 2
    It's the right way to force C through a C++ compiler. It's the wrong way to compile C, and the wrong way to convert C into C++. – Mike Seymour Sep 18 '13 at 18:22
  • @H2CO3 I fully understand that in C you don't cast the return value. However, a C++ compiler will complain. It is ugly, yes, but correct – C0deH4cker Sep 18 '13 at 18:23
  • @C0deH4cker It's only as correct as compiling C code with a C++ compiler. (Would you try to run Python code using the Perl interpreter?) –  Sep 18 '13 at 18:29
  • @H2CO3 I know that it isn't proper C++ code. I'm just answering the OP's horrible question. Just look at his code. It's for a keylogger. He clearly has no idea how to program and probably just copy and pasted bits and pieces of code together until he ended up with this mess. – C0deH4cker Sep 18 '13 at 18:34
  • @C0deH4cker Yeah I know, but I still believe that showing him the proper solution has more benefit than replacing his problem with another one. I understand your point of view and I know how you feel, but it's not correct from a pedagogical perspective. –  Sep 18 '13 at 18:36
  • It IS proper C++ code, after this fix. Not the preferred style, but certainly valid with well-defined behavior. – Ben Voigt Sep 18 '13 at 18:41
  • @BenVoigt In that comment I meant proper as in the generally correct way to do things in C++. You are correct though, it is proper, albeit hacky and bad style, C++ code. – C0deH4cker Sep 18 '13 at 18:43
  • @C0deH4cker: I certainly agree... as it also was copied from terrible style C code. I don't understand the opinion that compiling it with a C compiler magically makes it better code. – Ben Voigt Sep 18 '13 at 18:45
  • 1
    @BenVoigt Well in general, if this were really written in C++, it would follow C++ idioms such as using std::cout instead of printf for one thing. And it is still bad code either way. The variable naming is really what gets me. Teclas to me seems like a class, not a char array. – C0deH4cker Sep 18 '13 at 18:49
  • 1
    @C0deH4cker Now that's exact! I didn't even want to get into the naming convention war, but `Teclas` is really rather a type than a variable. –  Sep 18 '13 at 18:50
  • @C0deH4cker: The naming isn't bad, it's just not English. "Teclas" is Spanish for "keys". – Mike Seymour Sep 18 '13 at 18:51
  • @MikeSeymour I know that it's Spanish. It's the fact that the first letter is capitalized, which generally is used for naming types, not variables. He should have named the variable `teclas`. – C0deH4cker Sep 18 '13 at 18:52
  • @C0deH4cker: Sorry, my misunderstanding. It never occurred to me that you were reading anything into the capitalisation; there are so many conventions that I never infer any meaning from it. But good luck trying to convince the world to follow yours. – Mike Seymour Sep 18 '13 at 18:57
0

On the android NDK JNI, even with typecasting, old style or new style, the error still doesn't go away.

buffer = (char *) malloc(10);
xxxx=static_cast<char*>(calloc(1024,sizeof(char)));

To make the errors go away, an extra include needs to be added to the path and symbols.

Project -> properties -> C/C++ general -> Path and symbols

On the Includes tab/GNU C++, add the following path (with the appropriate gcc version 4.6, 4.8...) Of course on windows, the path would be be a windows path....

{NDKROOT}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.6/include

Fred F
  • 1,027
  • 1
  • 9
  • 18
0

If you can make sure there is no other error in your code, you can add g++ flag: -fpermissive to put the error into warning.
exp: g++ -fpermissive yourcode.cpp

franksai
  • 63
  • 5
  • Are you sure about this approach? When the compiler has a problem, you can't always solve it by saying that it's not a problem :-) – Dominique Jun 26 '18 at 13:04
  • Totally agree with you~ But if you only want to use `calloc(...)` in C++ just like in C (with no need to convert type by yourself). I think this is OK. Only use this when you can make sure your code is working, or you just try to turn c project into C++. – franksai Jul 01 '18 at 14:49