To understand the problem you're facing, you've to understand that two types, conceptually, are never the same (unless it's just a typedef
). int
and long
are 2 different types according to the language. Although your implementation may have them equally sized, they needn't be the same across all implementations. If you're aiming for portable code, making an assumption that they will be equally sized will lead to issues. How?
Say we've an implementation where sizeof(int)
is 4
and sizeof(long)
is 8
.
int i = 0;
long *l = &i; // good that the compiler rejects this
If this was allowed, then you'd be getting into undefined behaviour. Say i
lives at memory location 2000
, since it's 4-byte sized, accessing till 2003
is allowed, since this memory is owned by the program. What lies beyond that is unkown to the program(mer) and is thus inaccessible.
|<------------- i ------------->|
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0x00 | 0x00 | 0x00 | 0x00 |unknown|unknown|unknown|unknown|
+-------+-------+-------+-------+-------+-------+-------+-------+
2000 2001 2002 2003 2004 2005 2006 2007
|<---------------------------- *l ----------------------------->| // oops!
Since long
is of size 8
, making l
point to i
's address (2000
) would mean it'll point to 2000
and if you dereference the pointer i.e. do *l
to read what's in there, it'll try to read a long
of size 8
, there by trying to access 2004 to 2007 additional to reading 2000 to 2003. Thus leading you to undefined behaviour.
Avoid hacks like explicit conversion (type casting), do it the clean way. Use a temporary.
void need_long(long *data) { /* some code */ }
int i = 0;
long l = i; // temporary long to pass it to need_long
need_long(&l);
If you are OK with not being portable and are confident that int
and long
are of the same size, on your implementation, you may additionally pass -fpermissive
to allow this conversion which GCC prohibits by default.