Sams Teach Yourself C in 24 Hours (54 page)

BOOK: Sams Teach Yourself C in 24 Hours
4.23Mb size Format: txt, pdf, ePub

• How to declare and define unions

• How to initialize unions

• The differences between unions and structures

• Nested unions with structures

• Manipulating the bit field with struct

26 067231861x CH20 1/25/00 10:59 AM Page 334

334

Hour 20

What Is a Union?

A
union
is a block of memory that is used to hold data items of different types. In C, a union is similar to a structure, except that the data items saved in the union are overlaid in order to share the same memory location. That is, they all share the same starting address, unlike a structure where each member gets its own area of memory. More details on the differences between unions and structures are discussed in the following sections. First, let’s look at the syntax of unions.

Declaring Unions

The syntax for declaring a union is similar to the syntax for a structure. The following is an example of a union declaration:

union automobile {

int year;

char model[8];

int engine_power;

float weight;

};

Here union is the keyword that specifies the union data type. automobile is the tag name of the union. The variables year, model, engine_power, and weight, are members of the union, and are declared within the braces ({ and }). The union declaration ends with a semicolon (;).

Like a structure tag name, a union tag name is a label to a union, which is used by the compiler to identify the union.

Defining Union Variables

You can define union variables after declaring a union. For instance, the following union variables are defined with the union labeled with automobile from the previous section: union automobile sedan, pickup, sport_utility;

Here the three variables, sedan, pickup, and sport_utility, are defined as union variables.

Of course, you can declare a union and define variables of the union in a single statement.

For instance, you can rewrite the previous union declaration and definition like this: union automobile {

int year;

char model[8];

int engine_power;

float weight;

} sedan, pickup, sport_utility;

26 067231861x CH20 1/25/00 10:59 AM Page 335

Understanding Unions

335

Here three union variables, sedan, pickup, and sport_utility, are defined by the union of automobile in which there are four members of different data types. If you declare a union and define variables of the union in a single statement, and there are no further union variable definitions made with the union, you can omit the tag name of the union.

For instance, the tag name automobile can be omitted in the union definition like this: union {

int year;

char model[8];

int engine_power;

float weight;

} sedan, pickup, sport_utility;

Referencing a Union with
.
or
->

As well as being used to reference structure members, the dot operator (.) can be used in referencing union members. For example, the following statement assigns the value of 1997 to one of the members of the sedan union:

sedan.year = 1997;

Here the dot operator is used between the union name sedan and the member name year.

In addition, if you define a pointer ptr like this:

union automobile *ptr;

you can reference one of the union members in the following way:

ptr->year = 1997;

Here the arrow operator (->) is used to reference the union member year with the pointer ptr.

The program in Listing 20.1 gives another example of how to reference and assign values to the members of a union.

20

TYPE

LISTING 20.1

Referencing the Members of a Union

1: /* 20L01.c Referencing a union */

2: #include

3: #include

4:

5: main(void)

6: {

7: union menu {

8: char name[23];

continues

26 067231861x CH20 1/25/00 10:59 AM Page 336

336

Hour 20

LISTING 20.1

continued

9: double price;

10: } dish;

11:

12: printf(“The content assigned to the union separately:\n”);

13: /* reference name */

14: strcpy(dish.name, “Sweet and Sour Chicken”);

15: printf(“Dish Name: %s\n”, dish.name);

16: /* reference price */

17: dish.price = 9.95;

18: printf(“Dish Price: %5.2f\n”, dish.price);

19:

20: return 0;

21: }

After running the executable 20L01.exe of the program in Listing 20.1, I have the following output shown on the screen of my computer:

The content assigned to the union separately:

OUTPUT
Dish Name: Sweet and Sour Chicken

Dish Price: 9.95

The purpose of the program in Listing 20.1 is to show you how to reference
ANALYSIS
union members with the dot operator.

Inside the main() function, a union, called dish, is first defined with the union data type of menu in lines 7–10. There are two members, name and price, in the union.

Then the statement in line 14 copies the string “Sweet and Sour Chicken” into the character array name that is one of the union members. Note that the dish.name expression is used as the first argument to the strcpy() function in line 14. When the compiler sees the expression, it knows that you want to reference the memory location of name that is a member of the dish union.

The strcpy() function is a C function that copies the contents of a string, pointed to by the function’s second argument, into the memory storage pointed to by the function’s first argument. I included the header file string.h in the program before calling the strcpy() function. (See line 3.)

Line 15 prints out the contents copied to the name array by using the dish.name expression one more time.

The statement in line 17 assigns the value 9.95 to the double variable price, which is another member for the dish union. Note that the dish.price expression is used to reference the union member. Then line 18 displays the value assigned to price by calling the printf() function and passing the dish.price expression as an argument to the function.

26 067231861x CH20 1/25/00 10:59 AM Page 337

Understanding Unions

337

According to the results shown in the output, the two members of the dish union, name and price, have been successfully referenced and assigned corresponding values.

Unions versus Structures

You might notice that in Listing 20.1, I assigned a value to one member of the dish union, and then immediately printed out the assigned value before I moved to the next union member. In other words, I didn’t assign values to all the union members together before I printed out each assigned value from each member in the union.

I did this purposely because of the reason that is explained in the following section. So keep reading. (In Exercise 1 at the end of this lesson, you’ll see a different output when you rewrite the program in Listing 20.1 by exchanging the order between the statements in lines 15 and 17.)

Initializing a Union

As mentioned earlier in this lesson, data items in a union are overlaid at the same memory location. In other words, the starting memory location of a union is shared by all the members of the union at different times. The size of a union is at least as large as the size of the largest data item in the list of the union members. This way, it is large enough to hold any members of the union, one at a time. Therefore, it does not make sense to initialize all members of a union together because the value of the latest initialized member overwrites the value of the preceding member. You initialize a member of a union only when you are ready to use it. The value contained by a union is always the value that was last assigned to a member of the union.

For instance, if you declare and define a union on a 16-bit machine (that is, the int data type is 2 bytes long) like this:

union u {

char ch;

int x;

20

} a_union;

then the following statement initializes the char variable ch with the character constant

‘H’:

a_union.ch = ‘H’;

and the value contained by the a_union union is the character constant ‘H’. However, if the int variable x is initialized by the following statement:

a_union.x = 365;

26 067231861x CH20 1/25/00 10:59 AM Page 338

338

Hour 20

then the value contained by the a_union union becomes the value of 365. Figure 20.1

demonstrates the content change of the union during the two initializations.

FIGURE 20.1

0
x
1000

0
x
1001

0
x
1002

The content of the

a_union.ch = 'H'

'H'

a_union
union is the

same as the content

The memory block

assigned to one of its

of the union (in bytes)

members.

0
x
1000

0
x
1001

0
x
1002

a_union.x = 365

365

(Assume that 0
x
1000 is the start address

of the union.)

According to the ANSI C standard, a union can be initialized by assigning the first union member with a value. For instance, in the following statement:

union u {

char ch;

int x;

} a_union = {‘H’};

the a_union union is said to be initialized because the character constant ‘H’ is assigned to the first union member, ch.

If the first member of a union is a structure, the entire structure has to be initialized with a list of values before the union is said to be initialized.

Let’s see what will happen if you try to assign values to all members of a union together.

Listing 20.2 gives such an example.

LISTING 20.2

The Members of a Union Share the Same Memory

TYPE

Location

1: /* 20L02.c: Memory sharing in unions */

2: #include

3:

4: main(void)

5: {

6: union employee {

7: int start_year;

8: int dpt_code;

9: int id_number;

10: } info;

26 067231861x CH20 1/25/00 10:59 AM Page 339

Understanding Unions

339

11:

12: /* initialize start_year */

13: info.start_year = 1997;

14: /* initialize dpt_code */

15: info.dpt_code = 8;

16: /* initialize id */

17: info.id_number = 1234;

18:

19: /* display content of union */

20: printf(“Start Year: %d\n”, info.start_year);

21: printf(“Dpt. Code: %d\n”, info.dpt_code);

22: printf(“ID Number: %d\n”, info.id_number);

23:

24: return 0;

25: }

After the executable 20L02.exe is created and executed, the following output is
OUTPUT
displayed on the screen:

Start Year: 1234

Dpt. Code: 1234

ID Number: 1234

As you can see in Listing 20.2, a union called info has three int variable mem-ANALYSIS bers, start_year, dpt_code, and id_number. (See lines 6–10.) Then, these three union members are assigned with different values consecutively in lines 13, 15, and 17.

And in lines 20–22, you try to print out the values assigned to the three members.

However, the output shows that every member in the info union has the same value, 1234, which is the integer assigned to the third member of the union, id_number. Note that id_number is the member that is assigned with 1234 last; the info union does indeed hold the latest value assigned to its members.

The Size of a Union

You’ve been told that the members of a union all share the same memory location. The size of a union is at least as large as the size of the largest member in the union.

20

In contrast with a union, all members of a structure can be initialized together without any overwriting. This is because each member in a structure has its own memory storage.

The size of a structure is at least equal to the sum of the sizes of its members, instead of the size of the largest member as is the case with a union.

Listing 20.3 contains a program that measures the size of a union as well as the size of a structure. The structure has exactly the same members as the union.

26 067231861x CH20 1/25/00 10:59 AM Page 340

340

Hour 20

TYPE

LISTING 20.3

Measuring the Size of a Union

1: /* 20L03.c The size of a union */

2: #include

3: #include

4:

5: main(void)

6: {

7: union u {

8: double x;

9: int y;

10: } a_union;

11:

12: struct s {

13: double x;

14: int y;

15: } a_struct;

16:

17: printf(“The size of double: %d-byte\n”,

18: sizeof(double));

19: printf(“The size of int: %d-byte\n”,

20: sizeof(int));

21:

22: printf(“The size of a_union: %d-byte\n”,

23: sizeof(a_union));

24: printf(“The size of a_struct: %d-byte\n”,

25: sizeof(a_struct));

26:

27: return 0;

28: }

The compiler on your machine may generate several warning messages, something like

“unreferenced local variables.” This is because the a_union union and the a_struct structure are not initialized in the program. You can ignore the warning messages because they don’t apply to what we’re doing here. The following output is displayed on the screen of my computer after the executable 20L03.exe is created and executed: The size of double: 8-byte

Other books

The Lusitania Murders by Max Allan Collins
Coletrane by Rie Warren
Violet And Her Alien Matchmaker by Jessica Coulter Smith
Phosphorescence by Raffaella Barker
Swap Out by Golding, Katie