Needless pointer-casts in C - c++

I got a comment to my answer on this thread:
Malloc inside a function call appears to be getting freed on return?
In short I had code like this:
int * somefunc (void)
{
int * temp = (int*) malloc (sizeof (int));
temp[0] = 0;
return temp;
}
I got this comment:
Can I just say, please don't cast the
return value of malloc? It is not
required and can hide errors.
I agree that the cast is not required in C. It is mandatory in C++, so I usually add them just in case I have to port the code in C++ one day.
However, I wonder how casts like this can hide errors. Any ideas?
Edit:
Seems like there are very good and valid arguments on both sides. Thanks for posting, folks.

It seems fitting I post an answer, since I left the comment :P
Basically, if you forget to include stdlib.h the compiler will assume malloc returns an int. Without casting, you will get a warning. With casting you won't.
So by casting you get nothing, and run the risk of suppressing legitimate warnings.
Much is written about this, a quick google search will turn up more detailed explanations.
edit
It has been argued that
TYPE * p;
p = (TYPE *)malloc(n*sizeof(TYPE));
makes it obvious when you accidentally don't allocate enough memory because say, you thought p was TYPe not TYPE, and thus we should cast malloc because the advantage of this method overrides the smaller cost of accidentally suppressing compiler warnings.
I would like to point out 2 things:
you should write p = malloc(sizeof(*p)*n); to always ensure you malloc the right amount of space
with the above approach, you need to make changes in 3 places if you ever change the type of p: once in the declaration, once in the malloc, and once in the cast.
In short, I still personally believe there is no need for casting the return value of malloc and it is certainly not best practice.

This question is tagged both for C and C++, so it has at least two answers, IMHO:
C
Ahem... Do whatever you want.
I believe the reason given above "If you don't include "stdlib" then you won't get a warning" is not a valid one because one should not rely on this kind of hacks to not forget to include an header.
The real reason that could make you not write the cast is that the C compiler already silently cast a void * into whatever pointer type you want, and so, doing it yourself is overkill and useless.
If you want to have type safety, you can either switch to C++ or write your own wrapper function, like:
int * malloc_Int(size_t p_iSize) /* number of ints wanted */
{
return malloc(sizeof(int) * p_iSize) ;
}
C++
Sometimes, even in C++, you have to make profit of the malloc/realloc/free utils. Then you'll have to cast. But you already knew that. Using static_cast<>() will be better, as always, than C-style cast.
And in C, you could override malloc (and realloc, etc.) through templates to achieve type-safety:
template <typename T>
T * myMalloc(const size_t p_iSize)
{
return static_cast<T *>(malloc(sizeof(T) * p_iSize)) ;
}
Which would be used like:
int * p = myMalloc<int>(25) ;
free(p) ;
MyStruct * p2 = myMalloc<MyStruct>(12) ;
free(p2) ;
and the following code:
// error: cannot convert ‘int*’ to ‘short int*’ in initialization
short * p = myMalloc<int>(25) ;
free(p) ;
won't compile, so, no problemo.
All in all, in pure C++, you now have no excuse if someone finds more than one C malloc inside your code...
:-)
C + C++ crossover
Sometimes, you want to produce code that will compile both in C and in C++ (for whatever reasons... Isn't it the point of the C++ extern "C" {} block?). In this case, C++ demands the cast, but C won't understand the static_cast keyword, so the solution is the C-style cast (which is still legal in C++ for exactly this kind of reasons).
Note that even with writing pure C code, compiling it with a C++ compiler will get you a lot more warnings and errors (for example attempting to use a function without declaring it first won't compile, unlike the error mentioned above).
So, to be on the safe side, write code that will compile cleanly in C++, study and correct the warnings, and then use the C compiler to produce the final binary. This means, again, write the cast, in a C-style cast.

One possible error it can introduce is if you are compiling on a 64-bit system using C (not C++).
Basically, if you forget to include stdlib.h, the default int rule will apply. Thus the compiler will happily assume that malloc has the prototype of int malloc(); On Many 64-bit systems an int is 32-bits and a pointer is 64-bits.
Uh oh, the value gets truncated and you only get the lower 32-bits of the pointer! Now if you cast the return value of malloc, this error is hidden by the cast. But if you don't you will get an error (something to the nature of "cannot convert int to T *").
This does not apply to C++ of course for 2 reasons. Firstly, it has no default int rule, secondly it requires the cast.
All in all though, you should just new in c++ code anyway :-P.

Well, I think it's the exact opposite - always directly cast it to the needed type. Read on here!

The "forgot stdlib.h" argument is a straw man. Modern compilers will detect and warn of the problem (gcc -Wall).
You should always cast the result of malloc immediately. Not doing so should be considered an error, and not just because it will fail as C++. If you're targeting a machine architecture with different kinds of pointers, for example, you could wind up with a very tricky bug if you don't put in the cast.
Edit: The commentor Evan Teran is correct. My mistake was thinking that the compiler didn't have to do any work on a void pointer in any context. I freak when I think of FAR pointer bugs, so my intuition is to cast everything. Thanks Evan!

Actually, the only way a cast could hide an error is if you were converting from one datatype to an smaller datatype and lost data, or if you were converting pears to apples. Take the following example:
int int_array[10];
/* initialize array */
int *p = &(int_array[3]);
short *sp = (short *)p;
short my_val = *sp;
in this case the conversion to short would be dropping some data from the int. And then this case:
struct {
/* something */
} my_struct[100];
int my_int_array[100];
/* initialize array */
struct my_struct *p = &(my_int_array[99]);
in which you'd end up pointing to the wrong kind of data, or even to invalid memory.
But in general, and if you know what you are doing, it's OK to do the casting. Even more so when you are getting memory from malloc, which happens to return a void pointer which you can't use at all unless you cast it, and most compilers will warn you if you are casting to something the lvalue (the value to the left side of the assignment) can't take anyway.

#if CPLUSPLUS
#define MALLOC_CAST(T) (T)
#else
#define MALLOC_CAST(T)
#endif
...
int * p;
p = MALLOC_CAST(int *) malloc(sizeof(int) * n);
or, alternately
#if CPLUSPLUS
#define MYMALLOC(T, N) static_cast<T*>(malloc(sizeof(T) * N))
#else
#define MYMALLOC(T, N) malloc(sizeof(T) * N)
#endif
...
int * p;
p = MYMALLOC(int, n);

People have already cited the reasons I usually trot out: the old (no longer applicable to most compilers) argument about not including stdlib.h and using sizeof *p to make sure the types and sizes always match regardless of later updating. I do want to point out one other argument against casting. It's a small one, but I think it applies.
C is fairly weakly typed. Most safe type conversions happen automatically, and most unsafe ones require a cast. Consider:
int from_f(float f)
{
return *(int *)&f;
}
That's dangerous code. It's technically undefined behavior, though in practice it's going to do the same thing on nearly every platform you run it on. And the cast helps tell you "This code is a terrible hack."
Consider:
int *p = (int *)malloc(sizeof(int) * 10);
I see a cast, and I wonder, "Why is this necessary? Where is the hack?" It raises hairs on my neck that there's something evil going on, when in fact the code is completely harmless.
As long as we're using C, casts (especially pointer casts) are a way of saying "There's something evil and easily breakable going on here." They may accomplish what you need accomplished, but they indicate to you and future maintainers that the kids aren't alright.
Using casts on every malloc diminishes the "hack" indication of pointer casting. It makes it less jarring to see things like *(int *)&f;.
Note: C and C++ are different languages. C is weakly typed, C++ is more strongly typed. The casts are necessary in C++, even though they don't indicate a hack at all, because of (in my humble opinion) the unnecessarily strong C++ type system. (Really, this particular case is the only place I think the C++ type system is "too strong," but I can't think of any place where it's "too weak," which makes it overall too strong for my tastes.)
If you're worried about C++ compatibility, don't. If you're writing C, use a C compiler. There are plenty really good ones avaliable for every platform. If, for some inane reason, you have to write C code that compiles cleanly as C++, you're not really writing C. If you need to port C to C++, you should be making lots of changes to make your C code more idiomatic C++.
If you can't do any of that, your code won't be pretty no matter what you do, so it doesn't really matter how you decide to cast at that point. I do like the idea of using templates to make a new allocator that returns the correct type, although that's basically just reinventing the new keyword.

Casting a function which returns (void *) to instead be an (int *) is harmless: you're casting one type of pointer to another.
Casting a function which returns an integer to instead be a pointer is most likely incorrect. The compiler would have flagged it had you not explicitly cast it.

One possible error could (depending on this is whether what you really want or not) be mallocing with one size scale, and assigning to a pointer of a different type. E.g.,
int *temp = (int *)malloc(sizeof(double));
There may be cases where you want to do this, but I suspect that they are rare.

I think you should put the cast in. Consider that there are three locations for types:
T1 *p;
p = (T2*) malloc(sizeof(T3));
The two lines of code might be widely separated. Therefore it's good that the compiler will enforce that T1 == T2. It is easier to visually verify that T2 == T3.
If you miss out the T2 cast, then you have to hope that T1 == T3.
On the other hand you have the missing stdlib.h argument - but I think it's less likely to be a problem.

On the other hand, if you ever need to port the code to C++, it is much better to use the 'new' operator.

Related

Converting a pointer to X to an array of X

"Don't!" is the correct answer, but unfortunately it's not the one I need.
If I do:
size_t array_size = func_that_calc_array_size();
char *foo = new char[array_size];
if (array_size > 42)
foo[42] = 'X';
This is all perfectly legal, but my MISRA C++ code checker gives an error 5-0-15 on the foo[42], which says that "Array indexing shall be the only form of pointer arithmetic". This question has actually been asked before, but the question and answer missed a critical issue, namely that the documentation further states:
Array indexing shall only be applied to objects defined as an array type.
If you look at the documentation (a suspiciously bootleg copy can be found by searching for "misra c++ 2008 pdf") it has an example similar to:
void my_fn(uint8_t *p1, uint8_t p2[])
{
p1[5] = 0; // Non-compliant - p1 was not declared as array
p2[5] = 0; // Compliant
}
So, basically the code-checking tool matches the declaration to the usage. Is there any possible way to convert the pointer to an array?
In our real example, we are using OpenCV's uchar *cv::Mat::ptr(), so we can't just reserve a large-enough array.
I think the root of the problem here is char *foo = new char[array_size];. A MISRA checker is arguably allowed to assume that this is not an array, because all dynamic memory allocation is banned.
You could try to see if you get the same error when writing char array[10]={0}; char* foo = array; because then you can dismiss this as a false positive tool bug.
The purpose and rationale of the rule is to ban the form *(x + i) instead of x[i]. Nothing else. The rule does not block the use of the [] on a pointer operand.
Several MISRA rules are however in place to ensure that all pointer arithmetic is done with operands that point at the same array, to prevent undefined behavior.
MISRA-C:2004 and MISRA-C++:2008 also had some weird, vague requirement that function parameters should be declared as char param[] rather than char* param, but since that was nonsensical, all this talk about array style indexing was removed in MISRA-C:2012.
(In fact there's no such thing as "array style indexing" in C or C++, see Do pointers support "array style indexing"?)
The validity of the rule is quite dubious. In the example, p1 and p2 have exactly the same type: They are both pointers.
If p2 truly conforms to the rule, then the solution is to introduce a function, so that you can make use of the function-argument-array-to-pointer-adjustment. Here is an example with a lambda, but you can use a regular function as well:
char *foo = new foo[array_size];
if (array_size > 42)
[](char foo[]) {
foo[42] = 'X';
}(foo);
C++20 introduces std::span, which appears to be a solution to the problem:
std::span foo_span{foo, array_size};
if (array_size > 42)
foo_span[42] = 'X';
This uses a class overload of the subscript operator, and not pointer-subscript, so it appears to conform to the rule. std::span is probably not implementable without violating MISRA, but so are many other things in the standard library, so I suspect that is not a problem.
In our real example, we are using OpenCV's uchar *cv::Mat::ptr(), so we can't just reserve a large-enough array.
Perhaps to follow the spirit of the rule, rather than the letter, you should be passing a cv::Mat& into the function rather than char*.
P.S. I suspect that OpenCV does not conform to MISRA, so depending on it is probably not the best thing to do if the program has to conform to MISRA.

About keyword “const” in c++

According to the c++ grammar, const int* const p means that what p points to and it' value can't be rewritten.But today I found that if I code like this:
void f(const int* const p)
{
char* ch = (char*) p;
int* q = (int*) ch;
(*q) = 3; //I can modify the integer that p points to
}
In this condition,the keyword "const" will lose it's effect.Is there any significance to use "const"?
You are casting away the constness here:
char* ch = (char*) p;
Effectively, you are saying "I know what I am doing, forget you are const, I accept the consequences." C++ allows you to do stuff like this because sometimes it can be useful/necessary. But it is fraught with danger.
Note that if the argument passed to the function were really const, then your code would result in undefined behaviour (UB). And you have no way of knowing from inside the function.
Note also that in C++ it is preferable to make your intent clear,
int* pi = const_cast<int*>(p);
This makes it clear that your intention is to cast away the const. It is also easier to search for. The same caveats about danger and UB apply.
Your example will crash the app if const int* const p points to a compile time constant, when casting away constancy you need to be sure what you are doing.
C++ is a language for adults, extra power will never be sacrificed for ephemeral safety, it is the code author's choice whether to stay in a safe zone or to use cast operators and move one step closer to C/asm.
C/C++ will let you do many things that allow you to 'hurt' yourself. Here, casting away the const of p is "legal" because the compiler assumes you know what you are doing. Whether this is good coding style or not is another matter.
When you do something like this, you assume responsibility for any side effects and issues it could create. Here, if the memory pointed to in the parameter is static memory, the program will likely crash.
In short, just because you can do something doesn't mean it is a good idea.
The const keyword is a way to use the compiler to catch programming mistakes, nothing more. It makes no claims about the mutability of memory at runtime, only that the compiler should shout at you if you directly modify the value (without using C-style casts).
A C-style cast is pretty much a marker saying 'I know what I'm doing here'. Which in most instances is false.
Here you change the type of the pointer. Using such a cast (C-type) cast you can change it to any possible pointer with no problem.
The same way you can use c++ cast: const_cast<...>(...):
int* p_non_const = const_cast<int*>(p);
In this case (I hope) you see immediately what is happening - you simply rid of the constness.
Note that in your program you also don't need temprorary variable ch. You can do it directly:
int* q = (int*) p;
In principle you should not use such a cast, because correctly designed and written program doesn't need it. Usually the const_cast is used for quick and temporary changes in the program (to check something) or to use a function from some unproperly designed library.

TypeCasting Struct and Classes

I am very new to C++. Currently I am reviewing a source code where I saw some typecasting, but I didn't understand it.
Here is the code.
struct str {
char *a;
int b;
};
class F {
public:
char* val;
};
F f1;
Can anyone explain the below Assignement Please.or is that typecasting valid??
str* ptr = (str*) f1->val;
Can anyone explain the below Assignement Please.
It means "pretend that the val pointer points to an object of type str, even though it's declared to point to a completely different type char; give me that pointer and trust that I know what I'm doing".
That's assuming that the real code either declares F * f1;, or accesses it as f1.val; the code you've posted won't compile.
or is that typecasting valid??
If the pointer really does point to an object of the correct type, then it's valid; otherwise, using the pointer will cause the program to fail in all sorts of catastrophic ways.
Typecasting is something that should very rarely be necessary. If you really do need it, you should never (as in absolutely never, under any circumstances) use that C-style cast; it means "force the conversion with no checks whatsoever, as long as there's some way to do it, even if it makes absolutely no sense". Use static_cast or dynamic_cast when you can, and reinterpret_cast or const_cast when you're doing something really dodgy. And don't use any of them unless you know what you're doing, and have a very good reason for circumventing the type system.

Reinterpret_cast use in C++

Just a simple question,having this:
fftw_complex *H_cast;
H_cast = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*M*N);
what is the difference between:
H_cast= reinterpret_cast<fftw_complex*> (H);
and
H_cast= reinterpret_cast<fftw_complex*> (&H);
Thanks so much in advance
Antonio
Answer to current question
The difference is that they do two completely different things!
Note: you do not tell us what H is, so it's impossible to answer the question with confidence. But general principles apply.
For the first case to be sensible code, H should be a pointer (typed as void* possibly?) to a fftw_complex instance. You would do this to tell the compiler that H is really a fftw_complex*, so you can then use it.
For the second case to be sensible code, H should be an instance of a class with a memory layout identical to that of class fftw_complex. I can't think of a compelling reason to put yourself in this situation, it is very unnatural. Based on this, and since you don't give us information regarding H, I think it's almost certainly a bug.
Original answer
The main difference is that in the second case you can search your source code for reinterpret_cast (and hopefully ensure that every use is clearly documented and a necessary evil).
However, if you are casting from void* to another pointer type (is this the case here?) then it's preferable to use static_cast instead (which can also be easily searched for).
H_cast= reinterpret_cast<fftw_complex*> (H);
This converts the pointer-ish type inside H (or the integer itself, if H is an integer type) and tells the compiler "this is a pointer. Stop thinking whatever it was, it's a pointer now". H is used as something where you had stored a pointer-like address.
H_cast= reinterpret_cast<fftw_complex*> (&H);
This converts the address of H (which is a pointer to whatever type H is) into a pointer to "fftw_complex". Modifying the contents of H_cast will now change H itself.
You'll want the second if H is not a pointer and usually the first if it is. There are use cases for the other way around but they're uncommon and ugly (especially reinterpreting an int or - god forbid - a double as a pointer).
Pointer casts are always executed as a reinterpret_cast, so when casting from or to a void * there's no difference between a c-style cast, a static_cast or a reinterpret_cast.
Reinterpret_casts are usually reserved for the ugliest of locations where c-style casts and static_casts are used for innocuous casts. You basically use reinterpret_cast to tag some code as really-ugly:
float f = 3.1415f;
int x = *reinterpret_cast<int *>(&f);
That way, these ugly unsafe casts are searchable/greppable.

Is it possible to completely avoid C-style casts in C++?

I do not believe that it is possible to completely avoid C-style casts when writing C++. I was surprised to find out that I needed to use a C-style cast to avoid a compiler truncation warning:
short value_a = 0xF00D; // Truncation warning in VS2008
short value_b = static_cast<short>(0xF00D); // Truncation warning in VS2008
short value_c = (short)0xF00D; // No warning!
Are there other scenarios where there is no C++-style substitute for a C-style cast?
In C++, the C-style cast is defined (§5.4) in terms of C++-style casts. So for every cast you can do C-style, there's a matching C++-style cast (almost).
The "almost" is that C-style casts ignore base class accessibility. That is, there is no equivalent C++-style cast for the following:
struct foo {};
struct bar : private foo {};
bar b;
foo* f = (foo*)&b; // only way this can be done in a well-defined manner
So, no it's not strictly-speaking possible to completely ditch C-style casts. But the number of areas where a (combination of) C++-style casts doesn't suffice is few in count.
The above is the "language answer". What you're experiencing has nothing to do with C-style casts versus C++ casts, but just compiler implementation. Warnings are absolutely implementation-specific, and have nothing to do with C++.
So don't make the mistake of using your findings on this particular compiler in this particular situation for concluding things about C++ in general.
You are just trying to obfuscate your code, it is as simple as that. And the compiler is completely correct in telling you so.
If you have a precise idea what the assigned value should be, use that. My guess is that you have some unfounded presumption of short being 16 bit wide and that the sign representation of the target machine is two's complement. If that is so, assign -4083 to your variable. If you just need your variable as a bit vector, use an unsigned type.
As far as C is concerned the standard simply says about conversion from one integer type to another:
Otherwise, the new type is signed and
the value cannot be represented in it;
either the result is
implementation-defined or an
implementation-defined signal is
raised.
I imagine the the point of view of C++ with this respect is not much different. Other answers mention border cases where in C++ you would need a `C'-style cast to overrule all typechecks that C++ gives you. Feeling the need for them is an indication of bad design.
The case that you give as an example is certainly not one for which I would find any valid circumstances.
There are 4 c++ style casts, const_cast, reinterpret_cast, static_cast and dynamic_cast. They work as follows:
// const_cast casts away constness or adds it
const int const_integer = 5;
const_cast<int>(const_integer) = 3;
// static_cast will perform standards defined casts and will
// cast up or down a c++ inheritance hierarchy without checking the result of the cast
struct b {};
struct a : public b {};
struct c {};
double value = static_cast<double>(0.0f);
b* b_value = new b;
a* a_value = static_cast<a*>(b_value);
// dynamic_cast will perform any cast that static_cast will, but will check to see
// if the cast makes sense. If the values are not pointers, this cast can throw
b* value_b = new b;
a* value_a = new a;
b* new_b = dynamic_cast<b*>(value_a); // will return NULL
a* new_a = dynamic_cast<a*>(value_b); // will not return NULL
// reinterpret_cast will change any type to any other type, as long as the constness of the types is the same.
// the behavior of this cast is implementation specific.
double* a = new double;
*a = 0.0f;
int *b = reinterpret_cast<int*>(a);
A c-style cast in c++ simply tries to perform those casts in a specific order until one of them works. That order is as follows:
a const_cast
a static_cast
a static_cast followed by a const_cast
a reinterpret_cast, or
a reinterpret_cast followed by a const_cast.
So, in short, you can do any c-style cast in c++, because a c-style cast in c++ is just some arrangement of c++ style casts. Get it?
Yes, it is completely possible.
I never use C-style casts. I can write hundreds of thousands of lines of code without having to revert to using reinterpret_cast, C++'s closest cousin to the C-style cast. The only times I have to use reinterpret_cast is when doing socket programming -- a fairly narrow domain, in the big picture.
You don't need to use C-style casts, either. In your other post, you said
I could just use a negative value,
short my_value = -4083;
but in my code it is much more understandable to use hexadecimal.
So in this case you didn't have to use the cast. You chose to.
I was surprised to find out that I needed to use a C-style cast to avoid a compiler truncation warning
I see it the other way around: You use a C-style cast to prevent the compiler from warning you, and I see this as a severe disadvantage of the C-style cast.
if you feel you know what you're doing, then shut up the compiler for this one case by using a compiler-specific way. For example, for VC use something like
#pragma warning(push, disable: XXXX)
// code goes here
#pragma warning(pop)
In these cases, you can use reinterpret_cast. It was meant for a replacement of a unchecked C-style cast. The typical note here: this is unchecked cast, and should be avoided when possible by using the other available: const_cast, dynamic_cast, etc.