Making typedef Definitions

Submitted by Anonymous (not verified) on Sun, 03/10/2013 - 20:51

Making typedef Definitions

You can create your own names for data types with the help of the typedef keyword in C, and make those name synonyms for the data types. Then, you can use the name synonyms, instead of the data types themselves, in your programs. Often, the name synonyms defined by typedef can make your program more readable.

For instance, you can declare TWO_BYTE as a synonym for the int data type:

typedef  int  TWO_BYTE;

Then, you can start to use TWO_BYTE to declare integer variables like this:

TWO_BYTE i, j;

which is equivalent to

int i, j;

Remember that a typedef definition must be made before the synonym created in the definition is used in any declarations in your program.
Why Use typedef?

There are several advantages to using typedef definitions. First, you can consolidate complex data types into a single word and then use the word in variable declarations in your program. In this way, you don't need to type a complex declaration over and over, which helps to avoid typing errors.

The second advantage is that you just need to update a typedef definition, which fixes every use of that typedef definition if the data type is changed in the future.

typedef is so useful, in fact, that there is a header file called stddef.h included in the ANSI-standard C that contains a dozen typedef definitions. For instance, size_t is a typedef for the value returned by the sizeof operator.

The program shown in Listing 18.3 is an example of using typedef definitions.

TYPE
Listing 18.3. Using typedef definitions.


1:  /* 18L03.c: Using typedef definitions */
2:  #include <stdio.h>
3:  #include <stdlib.h>
4:  #include <string.h>
5:
6:  enum constants{ITEM_NUM = 3,
7:                 DELT='a'-'A'};
8:  typedef char *STRING[ITEM_NUM];
9:  typedef char *PTR_STR;
10: typedef char BIT8;
11: typedef int BIT16;
12:
13: void Convert2Upper(PTR_STR str1, PTR_STR str2);
14:
15: main()
16: {
17:    STRING str;
18:    STRING moon = {"Whatever we wear",
19:                   "we become beautiful",
20:                   "moon viewing!"};
21:    BIT16 i;
22:    BIT16 term = 0;
23:
24:    for (i=0; i<ITEM_NUM; i++){
25:      str[i] = malloc((strlen(moon[i])+1) * sizeof(BIT8));
26:      if (str[i] == NULL){
27:        printf("malloc() failed.\n");
28:        term = 1;
29:        i = ITEM_NUM;  /* break the for loop */
30:      }
31:      Convert2Upper(moon[i], str[i]);
32:      printf("%s\n", moon[i]);
33:    }
34:    for (i=0; i<ITEM_NUM; i++){
35:      printf("\n%s", str[i]);
36:      free (str[i]);
37:    }
38:
39:    return term;
40: }
41: /* function definition */
42: void Convert2Upper(PTR_STR str1, PTR_STR str2)
43: {
44:    BIT16 i;
45:
46:    for (i=0; str1[i]; i++){
47:      if ((str1[i] >= `a') &&
48:          (str1[i] <= `z'))
49:        str2[i] = str1[i] - DELT;
50:      else
51:        str2[i] = str1[i];
52:    }
53:    str2[i] = `\0';  /* add null character */
54: }


I have the following output displayed on the screen after running the executable, 18L03.exe, of the program in Listing 18.3:

OUTPUT

C:\app>18L03
Whatever we wear
we become beautiful
moon viewing!

WHATEVER WE WEAR
WE BECOME BEAUTIFUL
MOON VIEWING!
C:\app>

ANALYSIS

The purpose of the program in Listing 18.3 is to show you how to create your own names for data types such as char and int. The program in Listing 18.3 converts all characters in a Japanese haiku into their uppercase counterparts.

In lines 3 and 4, two more header files, stdlib.h and string.h, are included because the malloc() and strlen() functions are invoked later in the program.

An enum declaration is made in lines 6 and 7 with two enumerated names, ITEM_NUM and DELT. In addition, ITEM_NUM is assigned the value of 3 because there are three strings in the haiku. DELT contains the value of the difference between a lowercase character and its uppercase counterpart in the ASCII code. In line 7, the values of `a' and `A' are used to calculate the difference.

In lines 8_11, I define names, STRING, PTR_STR, BIT8, and BIT16, for a char array of pointers with three elements, a char pointer, a char, and an int data type, respectively, so that I can use these names as synonyms to these data types in the program.

For instance, the prototype of the Convert2Upper() function in line 13 contains two arguments that are all char pointers declared with PTR_STR.

In lines 17_20, two arrays of pointers, str and moon, are declared with STRING. moon is initialized to point to the strings of the Japanese haiku. In lines 21 and 22, two int variables, i and term, are declared with BIT16.

The for loop in lines 24_33 allocates enough memory space dynamically based on the size of the haiku. The Conver2Upper() function is then called in line 31 to copy strings referenced by moon to the memory locations pointed to by str and to convert all lowercase characters to their uppercase counterparts as well. Line 32 prints out the strings referenced by moon. The definition of the Conver2Upper() function is shown in lines 42_54.

In lines 34_37, another for loop is made to print out the content from the memory locations referenced by str. There are a total of three strings with uppercase characters in the content. After a string is displayed on the screen, the memory space allocated for the string is released by calling the free() function.

On the screen, you see two copies of the haiku—the original one and the one with all-uppercase characters.

Related Items

The #define and #undef Directives

The #define and #undef Directives

The #define directive is the most common preprocessor directive, which tells the preprocessor to replace every occurrence of a particular character string (that is, a macro name) with a specified value (that is, a macro body).

The C Preprocessor Versus the Compiler

The C Preprocessor Versus the Compiler

One important thing you need to remember is that the C preprocessor is not part of the C compiler.

What Is the C Preprocessor?

If there is a constant appearing in several places in your program, it's a good idea to associate a symbolic name to the constant, and then use the symbolic name to replace the constant throughout the program. There are two advantages to doing so. First, your program will be more readable.

Exercises : Answer the following Question

To help solidify your understanding of this hour's lesson, you are encouraged to answer the quiz questions and finish the exercises provided in the Workshop before you move to the next lesson.

Question and Answer

    Q Why is random access to a disk file necessary?