void* buffer = (void*)malloc(100);
By prefixing the malloc() function with (void*), what is being achieved, are we overriding the return type?
Nothing is achieved since malloc already returns a void pointer. This is equivalent to:
void* buffer = malloc(100);
The return type of the call to malloc is being explicitly cast to a void pointer. This is sort of redundant, as it already returns a void*, but is probably possibly present to clarify the developer's intention (or he just screwed up).
In this particular case, it does nothing. However, since C++ is much more strict than C regarding type safety, you generally need to cast the return of malloc:
void* x = malloc(100); //OK in C/C++
int* y = malloc(100); //OK in C, error in C++
int* z = (int*)malloc(100); //OK in C/C++, not recommended for C
However, since you use C++, I can't not tell you that you should use new instead.
Related
Why the following is wrong in C++ (But valid in C)
void*p;
char*s;
p=s;
s=p; //this is wrong ,should do s=(char*)p;
Why do I need the casting,as p now contains address of char pointer and s is also char pointer?
That's valid C, but not C++; they are two different languages, even if they do have many features in common.
In C++, there is no implicit conversion from void* to a typed pointer, so you need a cast. You should prefer a C++ cast, since they restrict which conversions are allowed and so help to prevent mistakes:
s = static_cast<char*>(p);
Better still, you should use polymorphic techniques (such as abstract base classes or templates) to avoid the need to use untyped pointers in the first place; but that's rather beyond the scope of this question.
The value doesn't matter, the type does. Since p is a void pointer and s a char pointer, you have to cast, even if they have the same value. In C it will be ok, void* is the generic pointer, but this is incorrect in C++.
By the way, p doesn't contains char pointer, it's a void pointer and it contains a memory address.
In general, this rule doesn't even have anything to do with pointers. It's just that you can assign values of some type to variables of other types, but not always vice versa. A similar situation would be this:
double d = 0.0;
int i = 0;
d = i; // Totally OK
i = d; // Warning!
So that's just something you have to live with.
There is a C-style string and I need to free the memory of it. I saw the following code sample but got confused about why (void*) is there.
char *data = "abc";
free( (void*)data );
Just two questions:
Why not simply free(data)?
Is (void*) conversion is a must?
Many thanks.
No, it's not necessary; the free() call is wrong and you cannot do this.
The cast is a huge blinking, bouncing, and screaming warning flag that the originating programmer was confused.
It's undefined behavior to pass a pointer not returned by a previous call to malloc() or one of its friends to free(). The cast is the least of the problems here.
You can never "free" the memory used by a string literal, since that memory is never allocated in some way that the program controls. It's not on the heap, and the heap is where dynamic memory allocation/deallocation typically happens. Your intention is wrong.
All you can do is set the pointer to NULL:
data = NULL;
that will not in any way "free" the memory used behind the scenes to hold the character data "abc" though, but that's fine.
Is an error to call free() since is not allocated using (m/c/re)alloc.
As pointed out by Jens Gustedt, a cast is only needed when you pass a const pointer because free() takes a void *, not a const void *:
const int *x = malloc(sizeof(int));
free((void *)x);
Without a cast you get:
demo.c:8:5: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default] In file included from demo.c:2:0: /usr/include/stdlib.h:488:13: note: expected ‘void *’ but argument is of type ‘const int *’
The cast is unnecessary. In C, a void* is implicitly convertible to and from other pointer types. free expects a void*, so no cast is required from another pointer type.
(Of course, as already pointed out, the code is obviously problematic altogether, so don't read into it too much.)
So, your premise here is incorrect, you do not need to free your "data" at all, it will most likely cause a crash if you do. You should only call free for data that has come from malloc, and "abc" is not one of those.
Second, if you are using C, then you should do:
char *data = malloc(4);
strcpy(data, "abc");
...
free(data);
In C++ we also can't convert a void * [the return value from malloc] to char *, so you would need char *data = (char *) malloc(4);, but free(data) should still work. Some compilers may issue warnings for this, and the standard MISRA, for example, does not allow ANY automatic conversions of C types, so explicit casts are REQUIRED here [not because the language says so, but because the MISRA standard does, and there are "checking software" that reads the source code to check these sort of criteria are met].
Of course, in "fresh"[1] C++, we should not use malloc or free, but new and delete:
char *data = new char[4];
strcpy(data, "abc");
....
delete [] data;
[1] As in "code written as C++ from scratch".
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.
Why the following is wrong in C++ (But valid in C)
void*p;
char*s;
p=s;
s=p; //this is wrong ,should do s=(char*)p;
Why do I need the casting,as p now contains address of char pointer and s is also char pointer?
That's valid C, but not C++; they are two different languages, even if they do have many features in common.
In C++, there is no implicit conversion from void* to a typed pointer, so you need a cast. You should prefer a C++ cast, since they restrict which conversions are allowed and so help to prevent mistakes:
s = static_cast<char*>(p);
Better still, you should use polymorphic techniques (such as abstract base classes or templates) to avoid the need to use untyped pointers in the first place; but that's rather beyond the scope of this question.
The value doesn't matter, the type does. Since p is a void pointer and s a char pointer, you have to cast, even if they have the same value. In C it will be ok, void* is the generic pointer, but this is incorrect in C++.
By the way, p doesn't contains char pointer, it's a void pointer and it contains a memory address.
In general, this rule doesn't even have anything to do with pointers. It's just that you can assign values of some type to variables of other types, but not always vice versa. A similar situation would be this:
double d = 0.0;
int i = 0;
d = i; // Totally OK
i = d; // Warning!
So that's just something you have to live with.
I got this problem:
invalid conversion from ‘void*’ to ‘uint8_t*’
When doing this:
int numBytes;
uint8_t *buffer;
buffer=malloc(numBytes); //error here, why?
or must I have to put it like this?
buffer=malloc(numBytes);
Please explain this.
You cannot implicitly cast from void * in C++ (unlike C in this respect). You could do:
buffer = static_cast<uint8_t *>(malloc(numBytes));
but really, you should just be using new/delete instead of malloc/free!
In C++ it is not allowed to simply assign a pointer of one type to a pointer of another type (as always there are exception to the rule. It is for example valid to assign a any pointer to a void pointer.)
What you should do is to cast your void pointer to a uint8_t pointer:
buffer = (uint8_t *) malloc (numBytes);
Note: This is only necessary in C++, in C it was allowed to mix and match pointers. Most C compilers give a warning, but it is valid code.
Since you're using C++ you could also use new and delete like this:
buffer = new uint8_t[numBytes];
and get rid of your buffer using:
delete[] buffer;
In general you shouldn't use malloc and free unless you have to interface with c libraries.
Malloc returns a void pointer; when you use it, you have to cast the return value to a pointer to whatever datatype you're storing in it.
buffer = (uint8_t *) malloc(numBytes);