I'm working now for some weeks with c99 focusing undefined behaviour. I wanted to test some strange code while trying to respect the rules. The result was this code:
(plz forgive me the variable names, i had eaten a clown)
int main(int arg, char** argv)
{
unsigned int uiDiffOfVars;
int LegalPointerCast1, LegalPointerCast2, signedIntToRespectTheRules;
char StartVar;//Only use to have an adress from where we can move on
char *TheAccesingPointer;
int iTargetOfPointeracces;
iTargetOfPointeracces= 0x55555555;
TheAccesingPointer = (char *) &StartVar;
LegalPointerCast2 = (int) &StartVar;
LegalPointerCast1 = (int) &iTargetOfPointeracces;
if ((0x80000000 & LegalPointerCast2) != (0x80000000 & LegalPointerCast1))
{
//as im not sure in how far
//"— Apointer is converted to other than an integer or pointer type (6.5.4)." is treating unsigned integers,
//im checking this way.
printf ("try it on next machine!\r\n");
return 1;
}
if ((abs (LegalPointerCast1) > abs (LegalPointerCast2)))
uiDiffOfVars = abs (LegalPointerCast1) - abs (LegalPointerCast2);
else
uiDiffOfVars = abs (LegalPointerCast2) - abs (LegalPointerCast1);
LegalPointerCast2 = (int) TheAccesingPointer;
signedIntToRespectTheRules = abs ((int) uiDiffOfVars);
if ((abs (LegalPointerCast1) > abs (LegalPointerCast2)))
TheAccesingPointer = (char *)(LegalPointerCast2 + signedIntToRespectTheRules);
else
TheAccesingPointer = (char *)(LegalPointerCast2 - signedIntToRespectTheRules);
printf ("%c\r\n", *TheAccesingPointer);//Will the output be an 'U' ?
return 0;
}
So this code is undefined behavior at its best. I get different results, whether I'm not accessing any memory-area, that i don't own, nor accessing any uninitialized memory. (afaik)
The first critical rule was, I'm not allowed to add or subtract pointer which lets them leaving their array bounds. But I'm allowed to cast a pointer into integer, there I'm able calculate with, as I want, am I not?
My second assumption was as I'm allowed to assign a pointer an address thats valid, its a valid operation to assign this calculated address to a pointer. Since I'm acting with a char pointer, there is also no break of strict aliasing rules, as a char* is allowed to alias anything.
So which rule is broken, that this causes UB?
are single Variables also to be understood as "Arrays", and I'm breaking this rule?
— Addition or subtraction of a pointer into, or just beyond, an array object and an integer type produces a result that does not point into, or just beyond, the same array object (6.5.6).
If so, I'm also allowed to do this?
int var;
int *ptr;
ptr = &var;
ptr = ptr + 1;
Because the result is almost pretty sure undefined behavior. compiling with MSVC2010 it puts out the expected "U", but on freeBSD using clang and gcc I get depending on optimization level pretty funny and different results each time. (what in my eyes shouldn't be as far the bahavior is defined).
So any ideas what is causing this nasal dragons?