Re: using "!!" in "c"



pemo wrote:
"Keith Thompson" <kst-u@xxxxxxx> wrote in message news:lnslrlmlv6.fsf@xxxxxxxxxxxxxxxxxx
"pemo" <usenetmeister@xxxxxxxxx> writes:
[snip]
!! is a good way of turning a scalar value into 1 or 0.
So is (value, 0) (i.e., a comma operator).  It turns a scalar value
into 1 or 0.  It just happens to be 0.

What's the point here?

I believe that Keith was just pointing out that your specification of what !! does was incomplete. What he wrote met your specification but would generally be pointless in real code (there are potentially some exceptions) and does not do what !! does.


!! maps 0 to 0, and any non-zero value to 1, for any scalar operand.

For example, this

    printf("%p\n", (void *)"boo");

will output some value that's not 0, and very unlikely to be 1, e.g.,
0040300

It will output some implementation-specific sequence of printing
characters.  The sequence may or may not look like a number.

Can you explain this comment too? Is it an allusion to some obscure minutiae in the std, like "In reality, an implementation is free to encode an address such that it is displayed in egyptian hieroglyphics"?

One very common format of output is something like "1234:5678", another is something like "0x12345678". You will note that the first does not look like a number because of the colon. Another common output is something like "(null)" which looks even less like a number. What %p prints can be in any format as long as it can be read by a %p in a scanf on that implementation and yield the original pointer. Frequently (though it is not required) it is whatever format is generally used in printed material for addresses, and when an address on a machine is not a simple thing (e.g. segment and offset as supported by x86 processors) that is quite likely to mean the output won't look like a simple integer. Egyptian hieroglyphics could legally be used as long they were part of the execution character set and scanf processed them appropriately.


However, this

    printf("%p\n", (void *)!!"boo");

will output 000001, e.g., '1'
That invokes undefined behavior.

"boo" yields a char* value.  The "!" operator yields 1 if its operand
compares equal to 0, 0 otherwise.  In this case, it compares the char*
value to a null pointer value.  Since "boo" cannot be a null pointer,
!"boo" is guaranteed to yield 0.  Applying "!" again yields the int
value 1.

So the above is equivalent to

   printf("%p\n", (void*)1);

The conversion of the int value 1 to void* may yield a trap
representation; passing this to printf() (or doing anything else with
it) invokes undefined behavior.

Well, it only conditionally invokes undefined behaviour. If it happens not to produce a trap representation then it is only implementation defined behaviour IIRC. Of course, it should still generally be treated as undefined behaviour.


Interesting, so something like this is basically illegal/non-portable now?

    void (* n)(void) = (void(*)(void))42;

    n();

Years ago I used to use something like the above for invoking interrupt routines.

What you show the above has *always* been non-portable. -- Flash Gordon Living in interesting times. Although my email address says spam, it is real and I read it. .



Relevant Pages

  • Re: freed address still readable?
    ... NOTE Possible undefined behavior ranges from ignoring the ... Hence, again, any attempt to use a pointer that has been free'd ... NOTE An unspecified value cannot be a trap representation. ... You've put an address to a struct object into pointer ...
    (comp.os.linux.development.system)
  • Re: function return pointer of int?
    ... However even evaluating fooinvokes undefined behavior, ... pointer becomes indeterminate. ... Using a trap representation in a value context is undefined behavior ...
    (comp.lang.c)
  • Re: printf("%p ", (void *)0);
    ... >> undefined behavior just by evaluating it before the call. ... Clearly assigning a stale pointer to another variable would be ... If it's a trap representation, ... it's been freed without invoking undefined behavior. ...
    (comp.lang.c)
  • Re: Controlling Static Data and Memory Organization...If Possible...
    ... resides invokes the wrath of undefined behavior because you are ... different pages of memory, and for the physical location of those pages ... to do with what "exactly" a pointer is physically in your program ... character at an address that is 1 higher than the one before it. ...
    (comp.lang.c)
  • Re: gcc knows about malloc()
    ... A pointer to a function of one type may be converted to a pointer to a ... no syntax errors doesn't cause undefined behavior. ... types are supposed to have the same representation. ... specifiers or qualifiers ...
    (comp.lang.c)