I came across one simple (maybe over simplified) implementation of the sizeof
operator in C, which goes as follows:
#include <stdio.h>
#define mySizeof(type) ((char*)(&type 1) - (char*)(&type))
int main() {
char x;
int y;
double z;
printf("mySizeof(char) is : %ld\n", mySizeof(x));
printf("mySizeof(int) is : %ld\n", mySizeof(y));
printf("mySizeof(double) is : %ld\n", mySizeof(z));
}
Note: Please ignore whether this simple function can work in all cases; that's not the purpose of this post (though it works for the three cases defined in the program).
My question is: How does it work? (Especially the char*
casting part.)
I did some investigations as follows:
#include <stdio.h>
#define Address(x) (&x)
#define NextAddress(x) (&x 1)
int main() {
int n = 1;
printf("address is : %lld\n", Address(n));
printf("next address is : %lld\n", NextAddress(n));
printf("size is %lld\n", NextAddress(n) - Address(n));
return 0;
}
The above sample program outputs:
address is : 140721498241924
next address is : 140721498241928
size is 1
I can see the addresses of &x
and &x 1
. Notice that the difference is 4, which means 4 bytes, since the variable is int
type. But, when I do the subtraction operation, the result is 1.
CodePudding user response:
What you have to remember here is that pointer arithmetic is performed in units of the size of the pointed-to type.
So, if p
is a pointer to the first element of an int
array, then *p
refers to that first element and the result of the p 1
operation will be the address resulting from adding the size of an int
to the address in p
; thus, *(p 1)
will refer to the second element of the array, as it should.
In your mySizeof
macro, the &type 1
expression will yield the result of adding the size of the relevant type to the address of type
; so, in order for the subsequent subtraction of &type
to yield the size in bytes, we cast the pointers to char*
, so that the subtraction will be performed in base units of the size of a char
… which is guaranteed by the C Standard to be 1 byte.
CodePudding user response:
Pointers carry the information about their type. If you have a pointer to a 4-byte value such is int
, and add 1
to it, you get a pointer to the next int
, not a pointer to the second byte of the original int
. Similarly for subtraction.
If you want to obtain the item size in bytes, it's necessary to force pointers to point to byte-like items. Hence the typecast to char*
.
See also Pointer Arithmetic