union, strcpy and main()

A

arnuld

I got this question in C while googling for top c interview questions.
There are several things which I could not comprehend:


#include <stdio.h>
#include <string.h>

int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);

return 0;
}

===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $



Q1: As per C90 (or C89, are they same ?) can we define a struct inside
another function ?

Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

Q4: Values in y are garbage, so it will print anything. Right ?
 
J

John Gordon

In said:
#include <stdio.h>
#include <string.h>
int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);
return 0;
}
===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

I assume it assigns 100 to the first member of y.
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

When you assigned 21.50 to x.c, you wiped out the values of all other
members of x. If you try to access the other members, you may or may not
get meaningful results.
Q4: Values in y are garbage, so it will print anything. Right ?

I assume y.a was assigned the value 100, so it should (and did) print 100
for y.a. In structs, only the most recently assigned member has a
meaningful value; the other members do not.
 
N

Nick Keighley

#include <stdio.h>
#include <string.h>
int main(void)
{
  typedef union
  {
    int a;
    char b[10];
    float c;
  } uni;
  uni x,y = {100};
  x.a = 50;
  strcpy(x.b,"hello");
  x.c = 21.50;
  printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
  printf("Union y : %d %s %f \n",y.a,y.b,y.c);
  return 0;
}
===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1..c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

I assume it assigns 100 to the first member of y.
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

When you assigned 21.50 to x.c, you wiped out the values of all other
members of x.  If you try to access the other members, you may or may not
get meaningful results.
Q4: Values in y are garbage, so it will print anything. Right ?

I assume y.a was assigned the value 100, so it should (and did) print 100
for y.a.  In structs, only the most recently assigned member has a
meaningful value; the other members do not.

in fact, I believe, accessing the "wrong" field of a union is
undefined behaviour. Never used 'em myself. So if I had to use unions
I'd have to read a manual.
 
P

Phil Carmody

arnuld said:
I got this question in C while googling for top c interview questions.
There are several things which I could not comprehend:


#include <stdio.h>
#include <string.h>

int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);

return 0;
}

===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $



Q1: As per C90 (or C89, are they same ?) can we define a struct inside
another function ?

Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

Q4: Values in y are garbage, so it will print anything. Right ?


These questions indicate that you've not learnt anything about unions
yet. Have a read of your K&R, or almost any other C resource.

Phil
 
J

James Kuyper

I got this question in C while googling for top c interview questions.
There are several things which I could not comprehend:


#include <stdio.h>
#include <string.h>

int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);

return 0;
}

===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $



Q1: As per C90 (or C89, are they same ?) can we define a struct inside
another function ?

You can define any user-defined type (a struct, a union, or an
enumeration) in a great many locations in C, including inside a function
body. Other odd places that are legal include the parameter list of a
function declaration, inside the declaration of another struct or union
type, and inside the type portion of a cast expression or a compound
literal. The corresponding tags have a restricted scope within which
they can be used.

Note: in C++, you can also declare user-defined types within a function
body. However, only one of the other places I listed above is allowed in
C++. You can declare a user-defined type inside the definition of a
class type - but the meaning is different from C: the so-defined type is
defined only in the context of the enclosing type.
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

It's exactly equivalent to:
uni x, y;
y.a = 100;
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

Because x.a, x.b, and x.c are all stored in overlapping memory
locations. Writing to any one of the three changes the stored
representation of the other two.

In C90, accessing a union member other than the one which was most
recently written was specified as having undefined behavior. In one of
the Technical Corrigenda, C99 was modified to remove that specification.
Footnote 82 clarifies that the defined behavior is now reinterpretation
of the bytes that make up a union member according to the type of that
member, which is what pretty much all implementations were doing anyway,
under C90. Note that if those bytes contain a trap representation for
that type, the behavior is still undefined. Note also that when you
assign to one member of a union, the bytes of that union which are not
used to store that member, but are used to store other members, take on
unspecified values, which can make it difficult to avoid creating a trap
representation.
Q4: Values in y are garbage, so it will print anything. Right ?

In C90, that was the case. In C99, if you know how a given
implementation represents 'int', 'char', and 'float', you can predict
whether it's safe to print y.b or y.c, and if so, you may be able to
predict what will be printed. There's no portable guarantees on either
the safety of printing them, or on the values that will be printed if it
is safe. The value is predicable only if the member you are printing is
no larger than the last one that was written to; otherwise, it's
representation includes bytes that were set to unspecified values when
the other member was written to.
 
N

Nick Keighley

On 11/28/2011 11:45 PM, arnuld wrote:

why you were being interviewed for a C programmign post by someone who
knew so little about it?

how do you mean "another function"? Which was the first function? Did
you mean "can I define a struct in a function?"? The answer to that is
"yes".
You can define any user-defined type (a struct, a union, or an
enumeration) in a great many locations in C, including inside a function
body. Other odd places [...]

why is it odd to define a type inside a function? An enumeration in
particular seems to make a great deal of sense. It's all about
limiting scope to only that which is necessary. Hiding the
implementation, avoiding namespace pollution etc.
that are legal include the parameter list of a
function declaration, inside the declaration of another struct or union
type, and inside the type portion of a cast expression or a compound
literal. The corresponding tags have a restricted scope within which
they can be used.

admittedly *these* are odd places!

<snip>
 
J

James Kuyper

why you were being interviewed for a C programmign post by someone who
knew so little about it?

I had thought that while the example code was from the "interview
questions" arnuld was talking about, questions Q1 through Q4 were from
arnuld himself about the example code. I didn't think about the
possibility that they might have been the actual "interview questions"
he was asking about, since they're so poorly written, and display a poor
understanding of C. However, you might be right.

how do you mean "another function"? Which was the first function? Did
you mean "can I define a struct in a function?"? The answer to that is
"yes".
You can define any user-defined type (a struct, a union, or an
enumeration) in a great many locations in C, including inside a function
body. Other odd places [...]

why is it odd to define a type inside a function? An enumeration in
particular seems to make a great deal of sense. It's all about
limiting scope to only that which is necessary. Hiding the
implementation, avoiding namespace pollution etc.
that are legal include the parameter list of a
function declaration, inside the declaration of another struct or union
type, and inside the type portion of a cast expression or a compound
literal. The corresponding tags have a restricted scope within which
they can be used.

admittedly *these* are odd places!

I was thinking primarily of those places when I called them "odd".
However, Q1 implies that the interviewer expected to have at least some
interviewees who were uncertain about whether a struct could be defined
inside a function (even though the example code involved a union, not a
struct).
 
J

John Gordon

In said:
In structs, only the most recently assigned member has a meaningful
value; the other members do not.

Of course I meant "unions" there, instead of "structs".
 
T

Tim Rentsch

John Gordon said:
In said:
#include <stdio.h>
#include <string.h>
int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);
return 0;
}
===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

I assume it assigns 100 to the first member of y.
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

When you assigned 21.50 to x.c, you wiped out the values of all other
members of x. If you try to access the other members, you may or may not
get meaningful results.
Q4: Values in y are garbage, so it will print anything. Right ?

I assume y.a was assigned the value 100, so it should (and did) print 100
for y.a. In unions, only the most recently assigned member has a
meaningful value; the other members do not.

This allegation is directly contradicted by a simple statement
in the Standard; see 6.5.2.3 p3.
 
T

Tim Rentsch

Nick Keighley said:
#include <stdio.h>
#include <string.h>
int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;
uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;
printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);
return 0;
}
===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

I assume it assigns 100 to the first member of y.
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

When you assigned 21.50 to x.c, you wiped out the values of all other
members of x. If you try to access the other members, you may or may not
get meaningful results.
Q4: Values in y are garbage, so it will print anything. Right ?

I assume y.a was assigned the value 100, so it should (and did) print 100
for y.a. In structs, only the most recently assigned member has a
meaningful value; the other members do not.

in fact, I believe, accessing the "wrong" field of a union is
undefined behaviour. [snip]

It isn't; it's well-defined as long as the member being accessed
is no larger than the member last stored.

It is possible that such an access can transgress into undefined
behavior for other reasons, eg, the stored value being accessed
is a trap representation of the type used for access. The access
itself, however, is defined.
 
T

Tim Rentsch

James Kuyper said:
I got this question in C while googling for top c interview questions.
There are several things which I could not comprehend:


#include <stdio.h>
#include <string.h>

int main(void)
{
typedef union
{
int a;
char b[10];
float c;
} uni;

uni x,y = {100};
x.a = 50;
strcpy(x.b,"hello");
x.c = 21.50;

printf("Union x : x.a = %d, x.b = %s, x.c = %f \n",x.a,x.b,x.c );
printf("Union y : %d %s %f \n",y.a,y.b,y.c);

return 0;
}

===================== OUTPUT =========================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-1.c
/home/arnuld/programs/C $ ./a.out
Union x : x.a = 1101791232, x.b = , x.c = 21.500000
Union y : 100 d 0.000000
/home/arnuld/programs/C $

[snip Q1 and response]
Q2: uni x,y = {100} is legal because it compiles. What exactly this line
means for value of y ?

It's exactly equivalent to:
uni x, y;
y.a = 100;
Q3: why x.b is not printing anything even when something was copied into
it ? Why x.a has some strange value instead of 50.

Because x.a, x.b, and x.c are all stored in overlapping memory
locations. Writing to any one of the three changes the stored
representation of the other two.

In C90, accessing a union member other than the one which was most
recently written was specified as having undefined behavior.

Implementation-defined, not undefined. Furthermore the intended
semantics under C90 are clearly meant to be the same as they are
under C99, just worded differently; see below.
In one of
the Technical Corrigenda, C99 was modified to remove that specification.
Footnote 82 clarifies that the defined behavior is now reinterpretation
of the bytes that make up a union member according to the type of that
member, which is what pretty much all implementations were doing anyway,
under C90.

The change in question arises from DR 283. DR 283 changes the
text of the Standard but not the semantics of the language;
all it does is add a footnote, with no changes to any normative
text. The change was put in only to clarify, not to change the
language. Quoting from the DR (written by Clark Nelson, a
committee member):

It is not perfectly clear that the C99 words have the same
implications as the C89 words.

Note: the DR mentions C89 but the text referenced in the DR
appears exactly the same in C90. The full DR is here:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_283.htm
Note that if those bytes contain a trap representation for
that type, the behavior is still undefined. Note also that when you
assign to one member of a union, the bytes of that union which are not
used to store that member, but are used to store other members, take on
unspecified values, which can make it difficult to avoid creating a trap
representation.

That's true if the member being accessed is larger than the
member last stored into, but not if the member being accessed is
the same size as, or smaller than, the last member stored.

In C90, that was the case.

Again, no; the behavior under C90 is the same as it is under C99.
In C99, [snip]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,818
Messages
2,569,736
Members
45,709
Latest member
DRISenaida

Latest Threads

Top