> No, this is since C90; nothing has changed in this area. NULL > doesn't mean "address 0", it means "nothing". The C statement > > if (ptr) > > doesn't mean "if ptr does not point to address zero", it means "if ptr > points to something".
A question then: How can I make a pointer to point to the integer located at address 0x0? It is a perfectly valid object, it exists, therefore I should be able to get its address? In fact, if I have a CPU that starts its data RAM at 0, then the first data object *will* reside at address 0 and thus taking its address will result in a pointer that has all its bits clear. Obviously that pointer then should not be equal to NULL, since it was obtained by taking the address of a valid object, that is, the pointer indeed points to something. Therefore, int *a = &first_object; int *b = (int *) 0; must result in different values in a and b. Will it? > I think you perhaps need to be a little less patronizing. I did not want to be patronising. I wanted to be sarcastic, yes, but not patronising at all. > Many of us, > myself included, have done a great deal of embedded programming and we > know what the issues are. You have written an incorrect program, and > you now know what was incorrect about it. Yes, I know. However, my problem is not that the program was not correct. It wasn't and I have admitted it from the beginning. My problem was that the compiler removed a test on an assumption. It could not *prove* that the pointer was not NULL. It merely *assumed* it. It can argue that what I did was wrong, but then it should have told me so. It did not say anything. It simply decided that since it saw me do something with a datum, the datum can not possibly be a certain value, because I should not do that with a datum if it is that certain value. It was wrong. If I write int x[ 10 ]; void foo( int i ) { bar( x[ i ] ); if ( i >= 10 || i < 0 ) { ... According to the C semantics you shouldn't under or overindex an array. Thus, you could safely remove the if(). Since I indexed a 10-element array with it, 'i' could not possibly be less than 0 or more than 9. Actually, the pointer (x+13) does not point to any valid object. Thus, (x+13) == NULL should evaluate true, shouldn't it? The same elimination should be true to this: a = b / c; if ( ! c ) for you can't divide by 0, thus c can not possibly be 0. Does gcc silently remove the if in the above case? > > So, pretty please, when the compiler detects that a language > > resembling to, but not really C is used and removes assumedly > > (albeit unprovenly) superfluos chunks of code to purify the > > misguided programmer's intent, could it please at least send a > > warning? > > In practice that's a lot harder than you might think. If we were to > issue a warning for every transformation we made based on the > semantics of the C language I'm sure people would complain. "You > can't dereference a NULL pointer" is a fundamental part of the > language. I think I see where your semantics and mine are different: You say: "You can't dereference a NULL pointer" I say: "You shouldn't dereference a NULL pointer" I shouldn't but I most certainly can. I can generate a NULL pointer where the compiler can not prove (at compile time) that it is NULL. If I dereference it, then whatever happens is my problem. I should not do that but I can and if I do, I take the consequences. The compiler, in my opinion, must not assume that just because something should not be done it can not possibly be done. Actually, it should not assume things at all. Rather, it should prove things before making a transformation. If it makes a transformation based on nothing more than its assumptions, then at least it should give me a warning. When you eliminate this condition: unsigned int x; if ( x >= 0 ) { then you are not assuming anything. You know, by definition, that the condition is true, it's a proven fact. Yet the compiler issues a warning. Or when facing this snipet: int x, y; for ( x = 0 ; x < 10 ; x++ ) if ( ! x ) y = 3; else y = y + x; the compiler complains that 'y' might be used uninitialised (well, gcc might be able to work out *that* one but a slightly more complex would be beyond its reach). Since it could not *prove* that y was on the LHS before being used on the RHS it issues a warning. However, when you eliminate this: z = *p; if ( ! p ) { you *assume* that p was not NULL, because according to the standard it should not have been. You have absolutely no way to prove it that it really wasn't. Yet you eliminate the if() without warning. See my problem? Zoltan