Specific pointer -> generic pointer -> boolean (i.e. implicit compare to 0) seems not to work as expected.
void main() { char* p; char* q; char xdata* xp = NULL; bit fail = FALSE; // This fails. if ( p = xp ) { fail = TRUE; } // This is ok. if ( ( q = xp ) == NULL ) { fail = TRUE; } }
It's always interesting to discuss whether an implementation of a C compiler conforms to the standard or not. Here is my 2 cents. The ISO C 1999 says: An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. ... Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal. Let's see if C51 conforms to that. Forgive me if I make mistakes here, since I only did C166. It's easy to satisfy the first requirement: a null pointer can't point to an object in C program. Just make sure that the linker doesn't put anything to where the null pointers point. The second requirement:
if ( (void*)0 != (void xdata*)((void*)0) ) printf("Oops! This is not ISO C behaviour.");
My point is that it's probably OK to break standard conformance in some places if it's justified by performance/simplicity/etc considerations. After all, if one wants standard C behaviour, they can limit themselves to using generic pointers only. I guess that this is the nub of the matter. If you write standard C code, you will always be getting generic pointers and, hence, standard C behaviour. Memory specific keywords are Keil extensions and if you choose to use them it is necessary to understand how they work in some detail.