HCL Interview Question
Software DevelopersCountry: India
If you don't cast with char then ((&x+1)-&x) will always return 1 because the difference will divided by the size of data type so suppose x is int type then the difference [((&x+1)-&x)] is here 4 and it will divide it with 4 so output is 1. so avoiding dividing with size of data type, we cast it with char because size of char is 1 and it won't effect the result.
This looks very confusing because what we know is normal arithmetic but what comes into picture here is pointer arithmetic, Now listen what is variable type in C - variable type is nothing but it tells us what value variable can hold(for ex: address, integer, character etc) and what type of operation we can perform on it (for example addition, subtraction, division etc)
Now lets come to pointer. When we declare pointer with some type it means that it tells compiler that when we do any operation(+,-,/,etc) on that pointer how many bytes it should move. for example if pointer type is
char *a;
and we do increment of that pointer
a+1
it will go to next byte address in all platform. similarly if we take integer pointer
int *b;
and and increment
b+1
it will go to 4th byte address assume int size on that platform is 4 bytes. Now here we are doing pointer subtraction : It turns out you can subtract two pointers of the same type. The result is the distance (in array elements) between the two elements. If you take integer pointer and do subtraction like below :
int x; (&x+1) - (&x)
it will give result as 1 because there is only one integer element between these two address that is pointer arithmetic!! now if cast it into char as below :
int x; (char *)(&x+1) - (char*)(&x)
it will give result as 4 because there are 4 character element between these two address. Finally the reason why void pointer will also work is :
Final conclusion: arithmetic on a void* is illegal in both C and C++.
GCC allows it as an extension, see Arithmetic on void- and Function-Pointers (note that this section is part of the "C Extensions" chapter of the manual). Clang and ICC likely allow void* arithmetic for the purposes of compatibility with GCC. Other compilers (such as MSVC) disallow arithmetic on void*, and GCC disallows it if the -pedantic-errors flag is specified, or if the -Werror-pointer-arith flag is specified (this flag is useful if your code base must also compile with MSVC).
The C Standard Speaks
Quotes are taken from the n1256 draft.
The standard's description of the addition operation states:
6.5.6-2: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type.
So, the question here is whether void* is a pointer to an "object type", or equivalently, whether void is an "object type". The definition for "object type" is:
6.2.5.1: Types are partitioned into object types (types that fully describe objects) , function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).
And the standard defines void as:
6.2.5-19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.
Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation.
Therefore you cannot perform pointer arithmetic on a void pointer.
Notes
Originally, it was thought that void* arithmetic was permitted, because of these sections of the C standard:
6.2.5-27: A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
Small try to explain mystery, please give feedback/comments.
ptrA - ptrB will return the number of elements of the type that the pointer is pointing to. The assumption being that both pointer A and B are pointing to elements of the same array OR one past the array...IIRC, this restriction is listed somewhere in the standard.
- smallchallenges March 21, 2016If you do not cast it to char *, then the pointer type of x will be chosen i.e. if it is an int, then the number of ints between the two pointers is returned. If you want to know the size of the object, then what you want is the number of char element types between the two i.e. casting it to char * will provide that for you.