Creating a New Data Type in C

Suppose you're writing a C program that frequently manipulates dates. You might create a new data type to represent dates, using the following structure:

struct date

{

int month;

int day;

int year;

};

This structure contains members for the month, day, and year.

To store a particular date, you can set the members of a date structure to the appropriate values:

struct date my_date;

my_date.month = 1;

my_date.day = 23;

my_date.year = 1985;

You cannot print a date by passing a date structure to printf. You must either print each member of the structure individually, or write your own function to print the structure as a whole, as follows:

void display_date( struct date *dt )

{

static char *name[] =

{

"zero", "January", "February", "March", "April", "May",

"June", "July", "August", "September", "October",

"November", "December"

};

printf( "%s %d, %d", name[dt->month], dt->day, dt->year );

}

This function prints the contents of a date structure, printing the month in string form, the day, and the year.

To perform other operations on dates, such as comparing two of them, you can compare the structure members individually, or you can write a function that accepts date structures as parameters and does the comparison for you.

When you define a structure type in C, you are defining a new data type. When you write functions to operate on those structures, you define the operations permitted on that data type.

This technique for implementing dates has some drawbacks:

It does not guarantee that a date structure contains a valid date. You could accidentally set the members of a structure to represent a date like February 31, 1985, or you might have an uninitialized structure whose members represent the one-thousand-and-fifty-eighth day of the eighteenth month of a certain year. Any function that blindly uses such a variable will generate nonsense results.

Once you've used the date data type in your programs, you cannot easily change its implementation. Suppose later you become concerned about the amount of space that your date variables are taking up. You might decide to store both the month and day using a single integer, either by using bit fields or by saving only the day of the year (as a number from 1 to 365). Such a change would save two bytes per instance. To make this change, every program that uses the date data type must be rewritten. Every expression that accesses the month or day as separate integer members must be rewritten.

You could avoid these problems with more programming effort. For example, instead of setting the members of a date structure directly, you could use a function that tests the specified values for validity. And instead of reading the members of the structure directly, you could call functions that returned the value of a structure's members. Unfortunately, many programmers don't follow such practices when using a new data type in C. They find it more convenient to access the members of a date structure directly. As a result, their programs are more difficult to maintain.

Unlike C, C++ was designed to support the creation of user-defined data types. As a result, you don't have to expend as much programming effort to create a data type that is safe to use.