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.
Related
For example, the line below compiles ok with gcc,
float *m = calloc(rows*cols, sizeof(float));
but g++ complains about the pointer type mismatch like below.
../../../../../YOLO/darknet/src/gemm.c:33:22: error: invalid
conversion from ‘void*’ to ‘float*
(maybe callc always returns void* in c++?)
Can I make g++ just ignore this pointer type mismatch error?
(I found this link but they say it's unavoidable. If we can use c code from inside c++ code without fixing this everywhere, it would be nice.)
(maybe callc always returns void* in c++?)
Yes. calloc always returns void*. Both in C and C++.
Can I make g++ just ignore this pointer type mismatch error?
I recommend to not attempt making the compiler to ignore the bug, but to fix the program instead. You can fix it like this:
float *m = static_cast<float*>(std::calloc(rows*cols, sizeof(float)));
Or compile the translation unit with a C compiler if it is written in C.
If we can use c code from inside c++
Solution: Don't use one language inside another. Write C in C and C++ in C++. Interaction between the languages is possible by linking the translation units together.
The solution to this problem is actually not to add a static_cast as eerorika suggests but compiling the C code with a C compiler. There are a number of subtle differences between C and C++ that can lead to unexpected results, and the compiler won't catch them all. So even if you change all the type warnings you might still end up with broken code.
To ensure that you can call the C code from C++ you should mark the code as extern "C" inside the C headers like so:
#ifdef __cplusplus
extern "C" {
#endif
[your definitions]
#ifdef __cplusplus
}
#endif
Regarding C++, read its draft standard n3337 or the newer n4860 draft or buy the official standard from ISO (or the equivalent standardizing organization in your country).
Regarding C, read its draft standard n1570 or buy the official standard from ISO.
For both C and C++, refer also to this website.
Read also this Modern C book about C, and that Programming -- Principles and Practice Using C++ book about C++.
If you are using a recent GCC, and if you are allowed to code some plugin for it, you might code a plugin which conditionally would correct the source code, or suggest and send some correction to your favorite editor (e.g. GNU emacs). Such an approach could take many weeks of effort.
As this answer correctly explains, you should improve your source code.
PS. I happen to be capable to write such a GCC plugin (see this draft tech report funded by the CHARIOT European project), but I need to get funded to do so. Feel free to contact me by email.
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 looking at Do I cast the result of malloc? and it appears that you should not cast the result in pure c code because it's potentially hides bugs and is redundant. But I also see people saying that c++ requires the cast, so should all c libraries cast the result of malloc because they could realistically be used in a c++ project?
it appears that you should not cast the result in pure c code because it's potentially hides bugs and is redundant
That is correct.
shouldn't all c libraries cast the result of malloc because they could realistically be used in a c++ project?
No. A C library can be used from within a C++ project but still be compiled as C.
No. If it's C code, it should be compiled as C, not as C++, and thus the compiler will allow the implicit cast from void* to some other pointer.
It is only when malloc is used in C++ code that you need to cast it - and it's in my view a "bad smell" - in other words, a sign that the code should be modernized to use new or vector or something along those lines. (Of course, there are valid reasons for doing this - for example, you could have some 10k lines of useful code, that you need to plumb into a C++ framework for something else - but typically, the best approach then is to write some C++ bindings that interface to those 10k lines and keep compiling that as C)
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
I am using CUDA to accelerate some parts of a C program. This program makes use of some C++ keywords as identifiers, so it doesn't compile as C++. Now that I changed it with CUDA, how can I compile it with NVCC?
For instance, I get the error:
table.h(65): error: expected an identifier
when compiling the code:
struct sw_table_position {
unsigned long private[4];
};
Which is perfectly valid C, but invalid C++. I am using CUDA 5.
NVCC compiles C++ code, not C code. Even if it pretends to consume C code in reality you just get a more C-like behavior, not a C compiler (see this post). For this reason private is a keyword and can't be used as identifier (like any other C++ keyword).
Actually --host-compilation C is deprecated (it shouldn't be used with nvcc) because in reality it doesn't do what you expect.