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?
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.
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(...).
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 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.
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
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
Related
I'm trying to use calloc in my program. With an explicit cast it compiles and runs fine, but when I try to remove the explicit cast of malloc I see the following error:
Assigning to '... *' (aka '....... *') from incompatible type 'void *'
How can I compile my code without an explicit cast of calloc in Xcode?
You are attempting to compile your C code as C++.
While it is true that some C code is also valid in C++, you have come across an example of C code that isn't valid in C++.
That is, C++ does not offer the implicit conversions to/from void * that C does.
You should always compile your C code using a C compiler, for the following three reasons:
You don't need to compile C code using a C++ compiler.
You're missing out on the best parts of C++.
You're missing out on the best parts of C.
The only reason people try to compile C code with a C++ compiler is that they anticipate using their C code in a C++ project. However, this is unnecessary because you can usually compile your C code using a C compiler, compile your C++ code using a C++ compiler and then link the two together. For example:
gcc -c c_code.c
g++ -c cpp_code.cpp
gcc cpp_library.o c_library.o
In C++, it is generally a bad idea to use *alloc functions. Those who program specifically in C++ will usually cringe at *alloc use.
In C, it is always a bad idea to explicitly cast void *, as the link you provided explains. Those who program specifically in C will cringe at unnecessary boilerplate that potentially introduces bugs.
Is there any type of casting (implicit, explicit) done in this line:
int *p= "hello there";
Moreover what is correctness of such a statement from C/C++ point of view ?
Note: it compiles on AVR-GCC and fails with other compilers.
"Is there any type of casting (implicit, explicit) done in this line:"
int *p= "hello there";
No, there isn't any casting done.
But in C++ you can use a reinterpret_cast<int*> along with a const_cast<char*> like follows:
int *p= reinterpret_cast<int*>(const_cast<char*>("hello there"));
See a working demo.
"Moreover what do you think about the correctness of such statement from (C,C++) point of view."
Well, that's totally left upon the user of such statement. It's certainly not recommendable to do so (because you're hitting not specified1 behavior), and dangerous if you're not a 100% sure about what you're doing.
But at least both languages support to do so.
The a bit shorter variant for C is:
int *p= (int*)"hello there";
"Note: it compiles on AVR-GCC and fails with other compilers."
Well, I don't know the version you're using for the AVR cross toolchain, but any halfway up-to-date version of GCC should give an error for this statement like
prog.cpp:3: error: cannot convert 'const char*' to 'int*' in initialization
See demo please
I'm using a fairly old version of GCC to make up that demo: g++ 4.3.2. The latest one is 5.x if I'm informed correctly, and I'm pretty sure that it's possible to build a cross toolchain for AVR with it.
1 Which is subtly different from undefined behavior. Just depends on what your hardware goes along with these pointer addresses, and the alignment settings.
to answer your question (ignoring the 'why do it' comments - which are correct)
You do
int *p=(int*)"hello there";
This code is illegal in C and C++. We might guess that AVR-GCC pretends that you had written:
int *p = (int *)"hello there";
You could perhaps try to confirm this by writing:
char *q = "hello there";
int *p = q;
and seeing if p and q hold the same address. (although that would not be completely conclusive either way).
It would be better to find out how to invoke your compiler in a mode where it will report errors or warnings for illegal code. Normally for gcc, -Wall -pedantic does this, and usually you'd also specify a standard version such as -std=c99 or -std=gnu99 .
Supposing the code is treated as int *p = (int *)"hello there";. This code may cause undefined or unexpected behaviour because the char array might not be correctly aligned for int.
Also, it will cause undefined behaviour if you read or write through p due to violating the strict aliasing rule, which says that reading or writing as int is only permitted for variables declared as int, or malloc'd space which (if being read) already has had an int written.
so I have some working code that calls gcc in a makefile. I then add my own class that uses the c++ vector stl, and I want to compile the same object.
If I just run the same command, I get an error:
fatal error: vector: No such file or directory
#include <vector>
If i try to use g++ instead to compile, I instead get a million errors, so I'm guessing that I shouldn't do that.
I googled how to add a c++ library to a gcc call, and I was told to use
gcc -lstdc++
However, that doesn't seem to have any effect. How can i go about building this object?
Would using g++ be the standard way? If I use g++ instead of gcc it seems like there are many conversion errors of this type:
globals.c:1381:50: error: invalid conversion from 'void*' to 'Global*' [-fpermissive]
struct Global *g = calloc(1,sizeof(struct Global)); /* allocate viewer context */
as well as an error of previous declaration:
d:\mingw\include\getopt.h:46:12: error: previous declaration 'int getopt(int, char* const*, const char*)' here
extern int getopt( int, char * const [], const char * );
There are quite a few issues here. First, the "gcc" executable will compile both C and C++ code, but it typically determines whether it should compile as C or C++ based on the file suffix. In your case, it appears to have tried to compile "globals.c" as a C source file instead of a C++ source file. The C compiler does not include the proper directory in the list of internal include paths so it will not even try to open the <vector> include. To compile as C++, you can force it with g++ or by changing the name of your source file to have a .cpp or .C suffix.
If you have more than one source file, then you are going to have more work to do. You will probably either need to compile everything with the C++ compiler, or will need to learn about "extern 'C'" and fix the interfaces between C++ and C. This may be more trouble than it is worth.
Next, you will need to address all of the errors in your compilation. It looks like the main problem you show has to do with typecasts. Those were more permissive under C than C++.
I would suggest that you take out the vector code, and keep using a pure C solution in your case. You have to perform the memory management yourself, but it isn't too hard. I have used realloc() in the past to resize memory. You'll need to keep track of a pointer to the allocated memory, the number of allocated objects and potentially the total size of the buffer.
The first error is because there is no automatic conversion from void * to other pointer types in c++. Which is not the case in c, so the code would compile correctly with a c compilier, to solve that you just need to cast the return value like this
Global *g = reinterpret_cast<Global *>(calloc(1,sizeof(Global)));
also notice that you don't need struct for declarations in c++.
I'd recommend the new operator, because if you add a constructor to struct Global it will automatically invoke the cosntructor, also
Global *g = new Global;
notice however that unlike calloc() the struct members here are not initialized to 0.
The important thing to know is that c and c++ are different languages, you can easily write code that would compile with a c compiler but not with a c++ compiler, like the code above, the other way it's even easier.
I was trying to declare an int array in C++ and found this problem. The following code runs fine on g++ compiler but the compilation fails on Visual Studio. I was following Bruce Eckel and found this code.
#include<iostream>
int main()
{
const int j = std::cin.get();
char buf[j];
}
Keeping j just an int would be a problem, that I understand. Since the value of j would be const during the run-time, the program should get compiled. Please correct me if I am wrong anywhere.
Since the value of j would be const during the run-time, the program should get compiled.
No, the const-ness of j is irrelevant here. C++ currently only supports statically-sized C-arrays. Its size must be a compile-time constant.
If you want an array of dynamic size, use std::vector.
The fact that g++ by default compiles this is a bit unfortunate (for compatibility). You should use the -pedantic flag when using g++ to ensure that such compiler extensions aren’t enabled (using compiler extensions of course isn’t bad in itself, but in this case there’s not really any advantage).
You are trying to define buf as a variable-length array. This is a feature of C (not C++) that is supported by g++ as a non-standard extension. Evidently your other compiler does not support it.
I would suggest turning buf into std::vector<char> (or indeed std::string?)
Variable length arrays are C99 feature both gcc and clang supports them as an extension in C++ but Visual Studio never did and even though they recently added support for C99 is it not supported in C++
Since you are developing in C++ unless you have a good reason to not use it then std::vector or std::string should be sufficient.
I had the same problem. It seems very difficult to create an array of which its length is stored as a variable. What I did is create an additional function:
void Class:: initMyArray(const int size) {
myArray = new int[size]
}
Now, you just have to call that function and give it your variable. I'm not sure whether this is a proper solution though (I'm not a C++ expert).
I generated a hash function with gperf couple of days ago. What I saw for the hash function was alien to me. It was something like this (I don't remember the exact syntax) :
unsigned int
hash(str, size)
register char* str;
register unsigned int size;
{
//Definition
}
Now, when I tried to compile with a C++ compiler (g++) it threw errors at me for not having str and size declared. But this compiled on the C compiler (gcc). So, questions:
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
How does the C compiler understand the definition? str and size are undeclared when they first appear.
What is the purpose of declaring str and size after function signature but before function body rather than following the normal approach of doing it in either of the two places?
How do I get this function to compile on g++ so I can use it in my C++ code? Or should I try generating C++ code from gperf? Is that possible?
1. C++ is not a superset, although this is not standard C either.
2/3. This is a K&R function declaration. See What are the major differences between ANSI C and K&R C?
.
4. gperf does in fact have an option, -L, to specify the language. You can just use -L C++ to use C++.
The Old C syntax for the declaration of a function's formal arguments is still supported by some compilers.
For example
int func (x)
int x
{
}
is old style (K&R style) syntax for defining a function.
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
Nopes! C++ is not a superset of C. This style(syntax) of function declaration/definition was once a part of C but has never been a part of C++. So it shouldn't compile with a C++ compiler.
This appears to be "old-school" C code. Declaring the types of the parameters outside of the parentheses but before the open curl-brace of the code block is a relic of the early days of C programming (I'm not sure why but I guess it has something to do with variable management on the stack and/or compiler design).
To answer your questions:
Calling C++ a "superset" of C is somewhat a misnomer. While they share basic syntax features, and you can even make all sorts of C library calls from C++, they have striking differences with respect to type safety, warnings vs. errors (C is more permissible), and compiler/preprocessor options.
Most contemporary C compilers understand legacy code (such as this appears to be). The C compiler holds the function parameter names sort of like "placeholders" until their type can be declared immediately following the function header name.
No real "purpose" other than again, this appears to be ancient code, and the style back in the day was like this. The "normal" approach is IMO the better, more intuitive way.
My suggestion:
unsigned int hash(register char *str, register unsigned int size)
{
// Definition
}
A word of advice: Consider abandoning the register keyword - this was used in old C programs as a way of specifying that the variable would be stored in a memory register (for speed/efficiency), but nowadays compilers are better at optimizing away this need. I believe that modern compilers ignore it. Also, you cannot use the & (address of) operator in C/C++ on a register variable.