I got confused in interpreting this line:
a = (char*) b;
while a and b are both declared to be of type char*.
Can anyone explain it to me please?
If they are of the same type, there is no need to use casting in the expression and it is the same as
a = b;
Edit: example casting with pointers
If you are using a C++ compiler, you need casting when calling malloc function otherwise you get an error message. This function returns a void* pointer and you need to explicitly cast it to its destination type as implicit conversion from void* has not been inherited from C.
Related
I am reading some open-source C code and encountering A a = (A) b; type conversion many times. For example,
static void hexdump(const void* pv, int len)
{
const unsigned char* p = (const unsigned char*) pv;
// some other code
}
A a = (A) b; code happens mainly when b is a pointer, void * pointer most often. I have C++ background. I think in C++, the assignment operator takes= care of the type conversion automatically? Because it already know that a is of type A.
Is the explicit type conversion necessary in C?
No, conversion from void* to char* in C (it's a common example to explain where they're different!) is implicit so casting is unnecessary (then wrong because it may hide a problem if you wrongly change char to int).
Quoting "The C Programming Language, 2nd edition" by K&R (§A.6.8):
Any pointer to an object may be converted to type void* without loss of information. If the result is converted back to the original pointer type, the original pointer is recovered. Unlike the pointer-to-pointer conversions discussed in Par.A.6.6, which generally require an explicit cast, pointers may be assigned to and from pointers of type void*, and may be compared with them.
Please note "If the result is converted back to the original pointer type" because is crucial: if instead of char* you had int* then it may be wrong because of memory alignment.
From C99 standard (§6.3.2.3) about when conversion is possible:
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Now let's see when can be implicit (thanks to mafso for very quick search), from C11 (n1570) §6.5.4p3:
Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.
Then §6.5.16.1:
One of the following shall hold: [...] the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right
You've got it the other way around: the cast is absolutely necessary in C++, but it is not necessary in C.
This will compile in C, but not in C++:
static void hexdump(const void* pv, int len) {
const unsigned char* p = pv;
...
}
It is not necessary in C but it helps silent compiler warnings for implicit casts in some cases.
In C++ however you need explicit casts to cast a void pointer into a pointer of a different type.
In my practice, no casting at first, though there's compiler warnings, after testing pass, casting is added to eliminate warnings.
In this case you are making a cast.
You are just saying for the compile. Hey, I'm sure that this is a type (A).
C++ style casts are checked by the compiler. C style casts aren't and can fail at runtime
It's called a cast. It means that it converts b in the (A) type.
char c = 'a'; // c is a char
int b = (int) c // you tell your compiler to interpret c as an int
This question already has answers here:
Do I cast the result of malloc?
(29 answers)
Closed 9 years ago.
Could someone explain to me why do some programmers use (char*) in front of the malloc? I know that it returns void but why do I want it to return just char memory? I'm sorry, I'm just a newbie in programming. Thank you
No need to cast return value of malloc as its return type is void*.
Can someone explain why do some programmers use (char *) in front of the malloc?
They are doing wrong (most probably) by casting it (in good programmers opinion).
As wiki says:
malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. The use of casting is required in C++ due to the strong type system, whereas this is not the case in C1. The lack of a specific pointer type returned from malloc is type-unsafe behavior according to some programmers: malloc allocates based on byte count but not on type. This is different from the C++ new operator that returns a pointer whose type relies on the operand.
One may "cast" this pointer to a specific type:
int *ptr;
ptr = malloc(10 * sizeof (*ptr)); /* without a cast */
ptr = (int *)malloc(10 * sizeof (*ptr)); /* with a cast */
ptr = reinterpret_cast<int *>(malloc(10 * sizeof (*ptr))); /* with a cast, for C++ */
There are advantages and disadvantages to performing such a cast.
Advantages to casting:
Including the cast allows a program or function to compile as C++.
The cast allows for pre-1989 versions of malloc that originally returned a char *.
Casting can help the developer identify inconsistencies in type sizing should the destination pointer type change, particularly if the pointer is declared far from the malloc() call.
Disadvantages to casting:
Under the ANSI C standard, the cast is redundant.
Adding the cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the standard requires that the C compiler assume malloc returns an int. If there is no cast, a warning is issued when this integer is assigned to the pointer; however, with the cast, this warning is not produced, hiding a bug. On certain architectures and data models (such as LP64 on 64-bit systems, where long and pointers are 64-bit and int is 32-bit), this error can actually result in undefined behavior, as the implicitly declared malloc returns a 32-bit value whereas the actually defined function returns a 64-bit value. Depending on calling conventions and memory layout, this may result in stack smashing. This issue is less likely to go unnoticed in modern compilers, as they uniformly produce warnings that an undeclared function has been used, so a warning will still appear. For example, GCC's default behavior is to show a warning that reads "incompatible implicit declaration of built-in function" regardless of whether the cast is present or not.
If the type of the pointer is changed, one must fix all code lines where malloc was called and cast (unless it was cast to a typedef).
1. Emphases are mine.
As the return type of malloc is void*, when you assign the result to a pointer, it is converted implicitly to the new type. So, there is no need for explicit casting. Actually, using an explicit cast is discouraged, as described here.
malloc returns void*, which is a generic pointer that can point to any type of data. The (char*) is an explicit type conversion, converting the pointer returned by malloc from a pointer to anything, to a pointer to char. This is unnecessary in C, since it is done implicitly, and it is actually recommended not to do this, since it can hide some errors.
If you need the code to compile as C++ too, and not just as C, you will however need the explicit conversion, since C++ doesn't perform the implicit conversion.
malloc() return a void*, as malloc() does not know how its caller will be using the memory it allocated on the heap.
So it's up to you, the caller to cast the (void*), into the appropriate type of pointer, that you want to use inside the memory.
(int*) to store integers.
(char*) to store characters etc..
Having said so, you don't have to explicitly cast the return of a malloc() call. And in some cases, doing so may result in bugs.
Kindly read up the issue here
What's wrong with casting malloc's return value?
Specifically, what's dangerous about casting the result of malloc?
The following two are the same but C99 standard leaves casting from void * to a function pointer undefined.
Can somebody explains how the second one works? Its a little bit confusing!
int (*fptr)(int);
fptr = (int (*)(int))dlsym(handle, "my_function");
int (*fptr)(int);
*(void **) (&fptr) = dlsym(handle, "my_function");
On the first line (of the second code paste) declares a function pointer (I imagine that you know that).
Now, dlsym(3) is a call that returns a void *.
So the second line can also be read as:
*((void **) (&fptr)) = dlsym(handle, "function");
Otherwise said: instead of casting the function result as int (*)(int), and affecting the given result to fptr; it casts a pointer on fptr (or it casts fptr's address: a pointer on a pointer) as a void**. Then it dereferences this pointer, effectively giving fptr (the same as the original one, but without the int (*)(int) type), which then gets the result of the dlsym call. It's just a way to 'trick' the compiler into not triggering warnings/errors about a type mismatch. Please also note that even if the syntax you chose is a matter of taste, it's something you should fully understand before you use it in any program you release.
I hope it helps ;)
The difference is the same as the one between:
float f = 3.14;
int i = (int)f;
and
float f = 3.14;
int i = *(int*)&f;
The first is a regular cast of the value, which in some cases (int <--> float, or back in the 8086 days near pointer <--> far pointer) causes some conversions; and in some cases (some casts between function pointers and regular pointers) doesn't even compile.
The second is a raw bitwise copy, which the compiler will always accept but bypasses any conversion and may lead to writing a variable into another variable of different size. Can be highly dangerous, especially with function pointers.
The reason the second version is legal is in the following part of the ISO Standard:
6.3.2.3 Pointers 1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be
converted to a pointer to void and back again; the result shall
compare equal to the original pointer.
(**void), as well as &fptr are pointers to objects (since &fptr is a pointer to a pointer to a function), so the cast in your second expression is explicitly allowed by the statement above. Your first expression is trying to convert a pointer to an object (rather a pointer to void which is a special case in the standard) to a pointer to a function (which is not an object), which is not allowed by the standard as you pointed out.
Knowing more C++ than C I wondered if someone could explain the reason why malloc() always returns a pointer of type void, rather than malloc having been implemented with some mechanism which allows it to return a pointer of the type the user passed in? It just seems a little "hacky" constantly explicitly casting the returned void pointer to the type you want.
Well, in C you don't have to do the cast, so your point is moot. That is, these two statements are 100% equivalent:
char *x = malloc(100);
char *y = (char *)malloc(100);
Conversions to and from void * are implicit in C. So, to address your question, the very reason malloc returns void * is so that you don't have to cast.
Besides that, in C there's no way to pass type information around, so doing something like:
char *x = malloc(100, char);
is not possible.
If you're in C++, the cast is necessary, but you shouldn't be using malloc anyway - that's what new is for, and it does handle the type information correctly.
It's not hacky at all, from C standard ISO/IEC 9899 2011, section 6.2.2.3:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
So a pointer to void* is a valid pointer to whatever type you want without the need of explicit casting.
In addition to this you can't dynamically pass a type to a function to let so that it will return the correct type, you can pass just the size itself (so malloc would be able to allocate size_t count * size_t size but not return the correctly type in any case).
C has no mechanism for "passing a type" at all. Also, in C, conversion from void* to a pointer of any other type is automatic (no cast is needed) so malloc works naturally in C. It's only in C++ where malloc requires casts to work.
There are two reasons, first, malloc doesn't know why you need memory. So it just return number of bytes asked to return. Secondly you cannot de-reference void * easily so it can help you to avoid accidents.
int *p;
p = (int *)malloc(sizeof(int)*10);
I have some confusions about what I read from the following site about memcpy()(and malloc()):
http://www.cplusplus.com/reference/cstring/memcpy/
In that page,the following 2 lines are clearly stated:
destination
Pointer to the destination array where the content is to be copied, type-casted to a pointer of type void*.
source
Pointer to the source of data to be copied, type-casted to a pointer of type const void*.
But immediately after that,in the code,there is no casting to void* in the following two lines where memcpy() is used:
memcpy ( person.name, myname, strlen(myname)+1 );
memcpy ( &person_copy, &person, sizeof(person) );
Please answer the following 2 questions arising from this premise:
1) In C's case(as opposed to C++) is it all right and advisable not to cast to void* the return type or the arguments in memcpy() just as it is all right and advisable not to cast to void* the return type of malloc() in C?If so,as I intuitively feel, why is it explicitly stated in that reputed site that we need to cast it to void* (even though it doesn't use that in the code).Is that site wrong about it?
2) Now the real contradiction about that reputed site.Consider the following
http://www.cplusplus.com/reference/cstdlib/malloc/
In the case of malloc() ,in the description, it is written as if it is optional to cast to void* the return type (exact words "..can be cast to the desired type.."),unlike in the case of memcpy() above where it is said that it is to be cast into void*.But while in memcpy() the casting is not done even though it is written that it is to be cast,in the case of malloc(),the casting to void* is done even though it's written it can be cast to void*.Now I see something wrong in this as for C we are not supposed to cast malloc()'s return to void*.
To put the discrepancies in a nutshell again lest the people answering get confused in my wordy description:
--Is it advisable in C not to cast to void* the return and arguments of memcpy()?
--Is that site wrong about malloc() as it casts malloc() return to void* in C code.
From ISO/IEC 9899:2011 of C language specification, section 6.3.2.3, page 55:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
So you basically never need to cast the result of a void* to the desired type, neither you need to do the opposite.
->for first question
memcpy, the cast is not required in C. It would be in C++.
->for second question
malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. The use of casting is required in C++ due to the strong type system, whereas this is not the case in C. The lack of a specific pointer type returned from malloc is type-unsafe behaviour according to some programmers: malloc allocates based on byte count but not on type. This is different from the C++ new operator that returns a pointer whose type relies on the operand
In C we directly assign void* to any type and vice-versa, we don't have to explicitly typecast.
int *i_ptr = (int *)0xABCD; //some address
printf("address :%p\n",i_ptr);
void *v_ptr = i_ptr; //no need to explictly typecast
printf("address :%p\n",v_ptr);
float *f_ptr = v_ptr; //this will throw error in cpp
printf("address :%p\n",f_ptr);
output:
address :0xabcd
address :0xabcd
address :0xabcd
All these are valid statements in C, but in CPP float *f_ptr = v_ptr will cause error invalid conversion from ‘void*’ to ‘float*’.