This is a new question in my "I don't understand pointers in C and C++" collection.
If I mix the bits of two pointers with equal values (pointing to the same memory address), that happen to have exactly the same bit representation, when one is dereferenceable and one is one past the end, what does the standard say should happen?
#include <stdio.h>
#include <string.h>
#include <assert.h>
// required: a == b
// returns a copy of both a and b into dest
// (half of the bytes of either pointers)
int *copy2to1 (int *a, int *b) {
// check input:
// not only the pointers must be equal
assert (a == b);
// also the representation must match exactly
int *dest;
size_t s = sizeof(dest);
assert(memcmp(&a, &b, s) == 0);
// copy a and b into dest:
// on "exotic" architectures, size does't have to be dividable by 2
size_t half = s/2; // = floor(s/2),
char *pa = (char*)&a, *pb = (char*)&b, *pd = (char*)&dest;
// copy half of a into dest:
memcpy (pd, pa, half);
// copy half of b into dest:
memcpy (pd+half, pb+half, s-half); // s-half = ceil(s/2)
//printf ("a:%p b:%p dest:%p \n", a, b, dest);
// check result
assert(memcmp(&dest, &a, s) == 0);
assert(memcmp(&dest, &b, s) == 0);
return dest;
}
#define S 1 // size of inner array
int main(void) {
int a[2][S] = {{1},{2}};
int *past = a[0] + S, // one past the end of inner array a[0]
*val = &a[1][0], // valid dereferenceable pointer
*mix = copy2to1 (past, val);
#define PRINT(x) printf ("%s=%p, *%s=%d\n",#x,x,#x,*x)
PRINT(past);
PRINT(mix);
PRINT(val);
return 0;
}
What I really want to understand is: what does "p points to object x" mean?
SEE ALSO
This question is a better version of my previous questions about array of arrays:
- Is memcpy of a pointer the same as assignment? which is a variation on my other question:
- Dereferencing an out of bound pointer that contains the address of an object (array of array)
and other related questions about pointer validity:
past
andval
should evaluate to the same value.a[0] + S
is outside the bounds ofa[0]
, but still within the bounds ofa
, so it should be a valid pointer. But honestly, masking two pointer values together to get another pointer is a use case I've never considered. – Truebloodx+y
when it was representable asint
and never output an incorrect value, but... – Cuisseprintf("%d",x+y);
would satisfy the requirements. If a different program running on a platform where overflow yields two's-complement reduction had a requirement that overflow must not disrupt program behavior, but could output any arbitrary value, the same code would be useable there. Mandating any particular overflow behavior would have required one of those programs to be longer and more complicated. – Cuisseint
must perform a two's-complement reduction, and possibly with an additional rule which would permitfor
loops to early-exit... – Cuissefor
loops only, so that code can indicate whether or not early-exit is acceptable by its choice of loop type). Such rules would not only allow the vast majority of the useful optimizations would be made possible by havingint
overflow be undefined, but more importantly would allow programmers to safely write code that could be optimized in such fashion. – Cuisse