Re: structure and union queries



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



Relevant Pages