I'm currently trying to avoid the pointer arithmetic workings in C to write an emulator.
Usually, if you add 1
to a pointer in C, you add the size of the pointed to object instead. However, I am trying to work with bits and bytes, so this is undesired.
I was wondering if I was using too many parentheses in this example:
*(int16_t *)(((intptr_t)bc)+sp)
And if not, then is it equivalent to this? :
*(int16_t *)((intptr_t)bc+sp)
sp
is a page-aligned stack address for my emulator (obtained via. mmap
without MAP_FIXED
set). It is an intptr_t
type.
bc
is the name of an int16_t *
type. It's a pointer to a combination of two int8_t
's.
What you're asking about is operator precedence. A full list can be found here.
The '+' operation occurs after a type cast operation. Therefore, you do not need the second layer of parenthesis because the intptr_t
cast is applied FIRST to bc
, then the result is added to sp
.
(((intptr_t)bc)+sp)
is equivalent t to ((intptr_t)bc+sp)
.
But this whole "avoid the pointer arithmetic" approach is not portable.
At least 3 concerns:
Pointers, converted to an integer, do not certainly maintain the math properties needed.
// possible outcome
uint16_t x[2];
printf("%llx\n", (unsigned long long) (intptr_t) &x[0]); // --> abcd0000
printf("%llx\n", (unsigned long long) (intptr_t) &x[1]); // --> abcd0010
The difference as integers may be 16 and not the hoped for 2 -- even if a difference of 2 is more common.
Further, with *(int16_t *)((intptr_t)bc+sp)
, if sp
is odd, (int16_t *)
can fail due to alignment restrictions.
Anti-aliasing issues occur too. @Andrew Henle
Such avoidance of pointer arithmetic though integers has various pitfalls - good luck.