Re: using "!!" in "c"



"pemo" <usenetmeister@xxxxxxxxx> writes:
> <snip>
>
>>> 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.
>
>
> If that *IS* the case, it seems um, rather unnecessarily pedantic - I
> believe that what I said was clear enough - and corrrect in as far as it
> went: and I also didn't say it was the only way to do something .... so why
> point out alternatives? Maybe it's necessary to produce litanies containing
> alternative possibilities for each non-exhaustive statement ever made here
> sometimes?

(A number of attributions were snipped. I wrote the text starting
with "So is (value, 0)", pemo wrote the text starting with "What's the
point here?", and Flash Gordon wrote the text starting with "I believe
that Keith was". Please leave attributions in place. Thanks.)

What you wrote was:

!! is a good way of turning a scalar value into 1 or 0.

That's not a useful specification unless you also specify *when*
it yields 0 and when it yields 1. By itself, it doesn't provide any
clue of why you'd want to turn a scalar value into 1 or 0. I was just
emphasizing the fact that !! maps 0 to 0 and all non-zero mappings
to 1. There are many many other possible mappings.

Whether I was being overly pedantic is a matter of opinion, of course.
I likely wouldn't have bothered mentioning it if I weren't commenting
on other things in your article.

>>>> 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". <snip>
>
> Ah, so it was as I expected - an allusion to some obscure minutiae [well, it
> is isn't it - letter-of-the-law-correct-or-not] that seems picky and
> generally non-constructive. The two examples you gave look like numbers to
> me. And I would hazard a guess that most every compiler outputs something
> similar - even if it doesn't *have to*. So, saying that a compiler *could*
> output this in a braille encoding of the morse-code interpretation of
> egyptian hieroglyphics is kinda like saying that there is a remote
> possibility that you *could* pick up a book which is written in English -
> but that you can't read - because the author decided to choose a remote
> vocabulary and to 'encode' his/her prose in such an impenetrable way as it
> make it more or less impossible. Both situations *could* exist, but both
> are, in reality, unlikely to - so what's the point in making a noise about
> it?

No, this is not "some obscure minutiae", this is part of a basic
understanding of the language.

Here's what the standard says about the "%p" format for the *printf()
functions:

The argument shall be a pointer to void. The value of the pointer
is converted to a sequence of printing characters, in an
implementation-defined manner.

There's also some wording for the *scanf() functions saying that it
can read the same format produced by *printf().

There is no implication that the output looks anything like a number,
and portable code cannot depend on any particular output format. It
happens that most implementations use something that looks like a
numeric format, possibly with extra decorations (leading "0x",
inserted ':', etc.). One system I just tried prints a hexadecimal
string *without* a leading "0x", such as "ffbff374", which happens to
be a valid identifier.

It's tempting to think that addresses are just another kind of number,
but that's a dangerous conceptual trap. They're often implemented
that way, but a C address or pointer value should be thought of as an
opaque entity that can be used to access other entities.

In any case, the example you chose didn't illustrate the point you
were making very well.

>>> 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.

That's legal but non-portable. The conversion of the int value 42 to
a pointer-to-function type yields an implementation-defined result; it
could be a trap representation. If there doesn't happen to be a
function of the proper type whose address is whatever you get by
converting the int value 42, Bad Things Will Happen.

Of course this is a perfectly legitimate thing to do as long as you
really know what's going on and you're aware that it's non-portable.

On some systems, converting an integer to a pointer-to-function might
*never* yield a meaningful value. (For example, I think the AS/400
has a very exotic format for function pointers.)

--
Keith Thompson (The_Other_Keith) kst-u@xxxxxxx <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
.



Relevant Pages

  • Re: Typecast clarification
    ... If 'int' is a four-byte type (which it is on many ... that 'char' and 'int' number the bits in the same order. ... because you cannot dereference a pointer to void. ... safety is automatic - for instance, when converting "signed char" to ...
    (comp.lang.c)
  • Re: Typecast clarification
    ... If 'int' is a four-byte type, there's 24 different byte orders theoretically possible, 6 of which would be identified as Little Endian by this code, 5 of them incorrectly. ... A conforming implementation of C could use the same bit that is used by an 'int' object to store a value of '1' as the sign bit when the byte containing that bit is interpreted as a char. ... there are implicit conversions between void* and any other pointer to to object type. ... If the value is currently of a type which has a range which is guaranteed to be a subset of the the range of the target type, safety is automatic - for instance, when converting "signed char" to "int". ...
    (comp.lang.c)
  • Re: Multiple date formats in a Table
    ... could choose a future date so they all sort at the end. ... However if you are set up to use UK format dates of dd/mm/yy, ... converting any entries where you know the full date. ... > iii) Once you've got a function that works, create a new query in design ...
    (microsoft.public.access.tablesdbdesign)
  • Re: Insufficient guarantees for null pointers?
    ... will the compiler know what the bounds are after converting that char * ... to an int *, if it could point to either of two arrays which happen to ... compares equal to the original pointer. ...
    (comp.std.c)
  • Re: vscanf and vprintf
    ... They take a pointer to a list of arguments rather than the arguments ... How can I write a function that takes a format string and a variable ... number of arguments, like printf, and passes them to printf to do most ... variable-length argument list, they accept a single va_list pointer. ...
    (comp.lang.c)