Velocity Reviews > structure and union queries

# structure and union queries

Flash Gordon
Guest
Posts: n/a

 04-12-2009
Richard wrote:
> Keith Thompson <(E-Mail Removed)> writes:
>
>> Flash Gordon <(E-Mail Removed)> writes:
>>> CBFalconer wrote:

>> [...]
>>>> Oh? Are you claiming that you can back up and find the previous
>>>> value emitted by rand? I don't think that is guaranteed.
>>> Wrong, it is guaranteed.
>>>
>>> The description of srand includes the following which explicitly
>>> guarantees that you can:
>>>
>>> | The srand function uses the argument as a seed for a new sequence of
>>> | pseudo-random numbers to be returned by subsequent calls torand. If
>>> | srand is then called with the same seed value, the sequence of
>>> | pseudo-random numbers shall be repeated. If rand is called before
>>> | any calls to srand have been made, the same sequence shall be
>>> | generated as when srand is ﬁrst called with a seed value of 1.

>> Yes, that means you can recover the previous value returned by rand()
>> *if* you've remembered the original value passed to srand() and the
>> number of times rand() has been called since then. But then you might
>> as well just remember the previous value returned by rand().

>
> It's not the same at all is it? Since you cant get the seed from the
> rand() can you? And without that you can not repeat the sequence.

<snip>

In this instance you can get the starting point by reading the code,
since the code in question did not call srand at all and as it was a
complete program this makes it entirely predictable.
--
Flash gordon

James Kuyper
Guest
Posts: n/a

 04-12-2009
CBFalconer wrote:
> James Kuyper wrote:
>> CBFalconer wrote:
>>

> ... snip ...
>>> #include <all needed>
>>>
>>> union un {
>>> char ch;
>>> int i;
>>> float d;
>>> } u;
>>>
>>> void setval(int val) {
>>> switch 3 * rand() / RAND_MAX { /* returning 0 thru 2 */
>>> case 0: u.ch = val;
>>> case 1: u.i = val;
>>> case 2: u.d = val;
>>> default: puts("error");
>>> }
>>> }
>>>
>>> int main(void) {
>>> int ct = 0;
>>>
>>> for (ct = 0; ct < 10; ct++) {
>>> setval(ct);
>>> printf("%c %d %f\n", u.ch, u.i, u.d);
>>> }
>>> return 0;
>>> }
>>>
>>> Please explain how the extraction code (u.i for example) knows
>>> what conversions to apply? Please ignore silly coding errors.

>> It's not supposed to apply any conversions, so that makes the
>> decision easy: it just takes the bits stored in u.ch, and
>> interprets them as a char. It takes the bits stored in u.i, and
>> interprets them as an int. It takes the bits stored in u.d, and
>> interprets them as a float. There's not a single conversion
>> anywhere in that process.

>
> As usual I have not been sufficiently specific. Imagine some sort
> of cast in each printf item, possibly implemented by a routine.
> i.e.:
>
> printf("%c %d %f\n", cnvt(u.ch), cnvt(u.i), cnvt(u.d));

%c requires an argument whose promoted type is char, %d requires one
that is compatible with int, %f requires one that is compatible with
float. If cnvt() were an ordinary function, it could only have one
return type, and no single type meets all of those requirements, so the
printf() call would have undefined behavior. If it's a function-like
macro or a <tgmath.h> - like function, then it could produce a result of
an acceptable type.

If it is a <tgmath.h>-like function, I can tell you that cnvt(u.ch) will
receive the value represented by the bits in u.ch, interpreted as a
char. cnvt(u.i) will receive the value represented by the bits in u.i,
interpreted as an int. cnvt(u.f) will receive the value represented by
the bits in u.f, interpreted as a float. If cnvt() is a function-like
macro, it's much harder to say anything meaningful about such code
without knowing precisely what cnvt() is.

I'm very unclear as the function and purpose of cnvt(). You describe the
behavior of cnvt as "some sort of cast", which is peculiar, since each
argument already has an appropriate type for the corresponding format
specifier. It would seem that the only useful purpose for involving
cnvt() would be if it returned a value different from that of it's
argument, which would only be the case for a cast if it were a cast to a
type of lower rank or a different signedness. But what would be the
point of doing that? I'm afraid I'm still at a loss as to what it is
you're trying to say.

Again, it looks like you think your arguing against an expectation or a
suggestion that all three print formats should print the same value. But
this is a suggestion that no one has made, and an expectation that no
one has expressed. Are you in fact aware of the fact that no one has
suggested any such thing?

Ben Bacarisse
Guest
Posts: n/a

 04-12-2009
CBFalconer <(E-Mail Removed)> writes:

> Ben Bacarisse wrote:
>> CBFalconer <(E-Mail Removed)> writes:

<big snip>
>>> #include <all needed>
>>>
>>> union un {
>>> char ch;
>>> int i;
>>> float d;
>>> } u;
>>>
>>> void setval(int val) {
>>> switch 3 * rand() / RAND_MAX { /* returning 0 thru 2 */
>>> case 0: u.ch = val;
>>> case 1: u.i = val;
>>> case 2: u.d = val;
>>> default: puts("error");
>>> }
>>> }
>>>
>>> int main(void) {
>>> int ct = 0;
>>>
>>> for (ct = 0; ct < 10; ct++) {
>>> setval(ct);
>>> printf("%c %d %f\n", u.ch, u.i, u.d);
>>> }
>>> return 0;
>>> }
>>>
>>> Please explain how the extraction code (u.i for example) knows what
>>> conversions to apply?

>>
>> It does not. As far as I can tell, you complicated the discussion by
>> suggesting that someone was expecting a conversion when no one was. I
>> think James was just pointing out that no one expected the Span^H^H^H^H
>> a conversion to take place.
>>
>>> Please ignore silly coding errors.

>>
>> Unfortunately, one of them means that in your example, we always know
>> that last member written, but that is incidental to the issue.

>
> Oh? Are you claiming that you can back up and find the previous
> value emitted by rand? I don't think that is guaranteed.

The sub-thread on the reversibility of rand is interesting but not
what I meant at all. There are enough problems with the code that any
guess as to the intent could be flawed, but taking your comment that 3
* rand() / RAND_MAX returns "0 thru 2" as the intent, then the
compiler always knows that u.d is the last member written regardless
of the return from rand() because the cases all "fall through".

Yes, I know this involves fixing some things and ignoring other,
equally probable, mistakes. It just seemed ironic that one of the
things I was being asked to ignore was a coding error that rendered
the whole example pointless.

--
Ben.

Richard Tobin
Guest
Posts: n/a

 04-13-2009
In article <%DtEl.483\$(E-Mail Removed)>,
James Kuyper <(E-Mail Removed)> wrote:

>%c requires an argument whose promoted type is char

You mean "int".

-- Richard
--
Please remember to mention me / in tapes you leave behind.

CBFalconer
Guest
Posts: n/a

 04-13-2009
Ben Bacarisse wrote:
> CBFalconer <(E-Mail Removed)> writes:
>

.... snip ...
>
>> Oh? Are you claiming that you can back up and find the previous
>> value emitted by rand? I don't think that is guaranteed.

>
> The sub-thread on the reversibility of rand is interesting but not
> what I meant at all. There are enough problems with the code that any
> guess as to the intent could be flawed, but taking your comment that 3
> * rand() / RAND_MAX returns "0 thru 2" as the intent, then the
> compiler always knows that u.d is the last member written regardless
> of the return from rand() because the cases all "fall through".
>
> Yes, I know this involves fixing some things and ignoring other,
> equally probable, mistakes. It just seemed ironic that one of the
> things I was being asked to ignore was a coding error that rendered
> the whole example pointless.

Well, all I wanted was some sort of non-backtraceable means of
selecting the form stored, so as to demonstrate the need to know
that form to read the value back from the union. Whew. That was
why I said ignore the errors.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

CBFalconer
Guest
Posts: n/a

 04-13-2009
Richard Tobin wrote:
> James Kuyper <(E-Mail Removed)> wrote:
>
>> %c requires an argument whose promoted type is char

>
> You mean "int".

Good point. I had missed that. I guess I very rarely use printf
for chars, and if I do they probably came from an int anyhow.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

James Kuyper
Guest
Posts: n/a

 04-13-2009
Richard Tobin wrote:
> In article <%DtEl.483\$(E-Mail Removed)>,
> James Kuyper <(E-Mail Removed)> wrote:
>
>> %c requires an argument whose promoted type is char

>
> You mean "int".

Actually, what I meant was "the same as the promoted type of char",
which is the same as "int", but had I remembered to address that issue,
I would have wanted to emphasize what the general rule was.

Ben Bacarisse
Guest
Posts: n/a

 04-13-2009
James Kuyper <(E-Mail Removed)> writes:

> Richard Tobin wrote:
>> In article <%DtEl.483\$(E-Mail Removed)>,
>> James Kuyper <(E-Mail Removed)> wrote:
>>
>>> %c requires an argument whose promoted type is char

>>
>> You mean "int".

>
> Actually, what I meant was "the same as the promoted type of char",
> which is the same as "int", but had I remembered to address that
> issue, I would have wanted to emphasize what the general rule was.

I have two nits. One may be a defect in the standard.

Nit the first: the promoted type of char can be unsigned int on some
odd implementations.

Nit the second: Richard is correct. %c requires an int argument. It
says so in the specification for fprintf. I had expected the wording
to be yours "the promoted type of char" or some such but it is not.

--
Ben.