USER-DEFINED DATA TYPES
Mr. Luyima Alex Cedric
aluyima@[Link]
+256 772 302 775/ +256 708045305
Mr. Mugejjera Emmanuel
emugejjera@[Link]
Phone: +256 703 186 705 / +256 772 959 183
Outline
Structures
Unions
Enumerations
C - STRUCTURES
Arrays allow to define type of variables that can hold several data items of the same kind. Similarly
structure is another user defined data type available in C that allows to combine data items of
different kinds.
Structures are used to represent a record. Suppose you want to keep track of diploma students in
a class. You might want to track the following attributes about each student:
• Name
• Regno
• Course
• Fees Code
Defining a Structure
To define a structure, you must use the struct statement. The struct statement defines a new data
type, with more than one member. The format of the struct statement is as follows:
struct [structure tag]
{
member definition;
member definition;
...
member definition;
} [one or more structure variables];
The structure tag is optional and each member definition is a normal variable definition, such as
int i; or float f; or any other valid variable definition. At the end of the structure's definition, before
the final semicolon, you can specify one or more structure variables but it is optional. Here is the
way you would declare the Student structure:
struct Student
{
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
} s1;
Accessing Structure Members
To access any member of a structure, we use the member access operator (.). The member access
operator is coded as a period between the structure variable name and the structure member that
we wish to access. You would use the keyword struct to define variables of structure type. The
following example shows how to use a structure in a program:
#include<stdio.h>
#include<string.h>
struct Student
{
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
};
int main()
{
struct Student Student1; //Declare Student1 of type Student
struct Student Student2; //Declare Student2 of type Student
/*The first student's details*/
strcpy([Link],"Kamugisha Edison");
strcpy([Link],"15/2/222/E/974");
strcpy([Link],"Diploma in Information Technology");
[Link]=11345;
/*The second student's details*/
strcpy([Link],"Namayanja Patricia");
strcpy([Link],"15/2/208/E/232");
strcpy([Link],"Diploma in Computer Science");
[Link]=11359;
/*Printing first student's details*/
printf("\nSTUDENT NAME: %s",[Link]);
printf("\nSTUDENT REGNO: %s",[Link]);
printf("\nSTUDENT COURSE: %s",[Link]);
printf("\nSTUDENT FEES CODE: %d",[Link]);
/*Printing first student's details*/
printf("\n\nSTUDENT NAME: %s",[Link]);
printf("\nSTUDENT REGNO: %s",[Link]);
printf("\nSTUDENT COURSE: %s",[Link]);
printf("\nSTUDENT FEES CODE: %d",[Link]);
return 0;
}
When the above code is compiled and executed, it produces the following result
C - UNIONS
A union is a special data type available in C that allows to store different data types in the same
memory location. You can define a union with many members, but only one member can contain
a value at any given time. Unions provide an efficient way of using the same memory location for
multiple-purpose.
Defining a Union
To define a union, you must use the union statement in the same way as you did while defining a
structure. The union statement defines a new data type with more than one member for your
program. The format of the union statement is as follows:
union [union tag]
{
member definition;
member definition;
...
member definition;
} [one or more union variables];
The union tag is optional and each member definition is a normal variable definition, such as int
i; or float f; or char name[20] any other valid variable definition. At the end of the union's
definition, before the final semicolon, you can specify one or more union variables but it is
optional. Here is the way you would define a union type named Student having three members
Name, Regno, Course and Feescode:
union Student
{
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
} Student1;
Now, a variable of Student type can store either strings of characters (i.e. Name, Regno or
Course) or an integer (Feescode). It means a single variable, i.e., same memory location, can be
used to store multiple types of data. You can use any built-in or user defined data types inside a
union based on your requirement.
The memory occupied by a union will be large enough to hold the largest member of the union.
For example, in the above example, Data type will occupy 100 bytes of memory space because
this is the maximum space which can be occupied by a character string (Course). The following
example displays the total memory size occupied by the above union:
#include<stdio.h>
#include<string.h>
union Student
{
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
};
int main()
{
union Student S1; //Declare Student1 of type Student
printf("\nThe size of memory occupied by Student1 is: %d bytes", sizeof(S1));
return 0;
}
When the above code is compiled and executed, it produces the following result:
The size of memory occupied by Student1 is: 100 bytes
Accessing Union Members
To access any member of a union, we use the member access operator (.). The member access
operator is coded as a period between the union variable name and the union member that we
wish to access. You would use the keyword union to define variables of union type. The
following example shows how to use unions in a program:
#include<stdio.h>
#include<string.h>
union Student {
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
};
int main()
{
union Student Student1; //Declare Student1 of type Student
/*The first student's details*/
strcpy([Link],"Kamugisha Edison");
strcpy([Link],"15/2/222/E/974");
strcpy([Link],"Diploma in Information Technology");
[Link]=11345;
/*Printing first student's details*/
printf("\nSTUDENT NAME: %s",[Link]);
printf("\nSTUDENT REGNO: %s",[Link]);
printf("\nSTUDENT COURSE: %s",[Link]);
printf("\nSTUDENT FEES CODE: %d",[Link]);
return 0;
}
When the above code is compiled and executed, it produces the following result:
Here, we can see that the values of Name, Regno and Course members of union got corrupted
because the final value assigned to the variable has occupied the memory location and this is the
reason that the value of Feescode member is getting printed accurately.
Now let's look into the same example once again where we will use one variable at a time which
is the main purpose of having unions:
#include<stdio.h>
#include<string.h>
union Student {
char Name[50];
char Regno[20];
char Course[100];
int Feescode;
};
int main()
{
union Student Student1; //Declare Student1 of type Student
strcpy([Link],"Kamugisha Edison");
printf("\nSTUDENT NAME: %s",[Link]);
strcpy([Link],"15/2/222/E/974");
printf("\nSTUDENT REGNO: %s",[Link]);
strcpy([Link],"Diploma in Information Technology");
printf("\nSTUDENT COURSE: %s",[Link]);
[Link]=11345;
printf("\nSTUDENT FEES CODE: %d",[Link]);
return 0;
}
When the above code is compiled and executed, it produces the following result
Here, all the members are getting printed very well because one member is being used at a time.
Difference between union and structure
Though unions are similar to structure in so many ways, the difference between them is crucial to
understand. This can be demonstrated by this example:
#include <stdio.h>
union job
{
//defining a union
char name[32];
float salary;
int worker_no;
}u;
struct job1
{
char name[32];
float salary;
int worker_no;
}s;
int main()
{
printf("size of union = %d", sizeof(u));
printf("\nsize of structure = %d", sizeof(s));
return 0;
}
Output
size of union = 32
size of structure = 40
There is difference in memory allocation between union and structure as suggested in above
example. The amount of memory required to store a structure variable is the sum of memory size
of all members.
But, the memory required to store a union variable is the memory required for largest element of
an union.
C - ENUMERATION
An enumeration is a user-defined data type consists of integral constants and each integral
constant is give a name. Keyword enum is used to defined enumerated data type. enum
type_name{ value1, value2,...,valueN };
Here, type_name is the name of enumerated data type or tag. And value1, value2,....,valueN are
values of type type_name.
Defining Enumerations
You define an enumeration using the enum keyword, followed by the name of the enumeration
(this is optional), followed by a list of constant names (separated by commas and enclosed in
braces), and ending with a semicolon.
enum fruit {grape, cherry, lemon, kiwi};
That example above defines an enumeration, fruit, which contains four constant integer values,
grape, cherry, lemon, and kiwi, whose values are, by default, 0, 1, 2, and 3, respectively. You can
also specify one or more of the values explicitly:
enum more_fruits {banana = -17, apple, blueberry, mango};
That example defines banana to be −17, and the remaining values are incremented by 1: apple is
−16, blueberry is −15, and mango is -14. Unless specified otherwise, an enumeration value is equal
to one more than the previous value (and the first value defaults to 0). You can also refer to an
enumeration value defined earlier in the same enumeration:
enum yet_more_fruit {kumquat, raspberry, peach, plum = peach + 2};
In that example, kumquat is 0, raspberry is 1, peach is 2, and plum is 4. You can’t use the same
name for an enum as a struct or union in the same scope.
Declaring Enumerations
You can declare variables of an enumeration type both when the enumeration is defined and
afterward. This example declares one variable, named my_fruit of type enum fruit, all in a single
statement:
enum fruit {banana, apple, blueberry, mango} my_fruit;
while this example declares the type and variable separately:
enum fruit {banana, apple, blueberry, mango};
enum fruit my_fruit;
(Of course, you couldn’t declare it that way if you hadn’t named the enumeration.) Although such
variables are considered to be of an enumeration type, you can assign them any value that you
could assign to an int variable, including values from other enumerations. Furthermore, any
variable that can be assigned an int value can be assigned a value from an enumeration. However,
you cannot change the values in an enumeration once it has been defined; they are constant values.
For example, this won’t work:
enum fruit {banana, apple, blueberry, mango};
banana = 15; /* You can’t do this! */
Enumerations are useful in conjunction with the switch statement, because the compiler can warn
you if you have failed to handle one of the enumeration values. Using the example above, if your
code handles banana, apple and mango only but not blueberry, GCC can generate a warning.
The program below illustrates an example of the enumerated type:
#include <stdio.h>
enum week{Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
int main()
{
enum week today;
today=Thursday;
printf("Today is the %d th day of the week.",today);
return 0;
}
When the above code is compiled and executed, it produces the following result: Today
is the 4 th day of the week.
The benefits of using enum over #define constant?
The use of an enumeration constant (enum) has many advantages over using the traditional
symbolic constant style of #define. These advantages include a lower maintenance requirement,
improved program readability, and better debugging capability. The first advantage is that
enumerated constants are generated automatically by the compiler. Conversely, symbolic
constants must be manually assigned values by the programmer.
For instance, if you had an enumerated constant type for error codes that could occur in your
program, your enum definition could look something like this:
enum Error_Code
{
OUT_OF_MEMORY,
INSUFFICIENT_DISK_SPACE,
LOGIC_ERROR,
FILE_NOT_FOUND
};
In the preceding example, OUT_OF_MEMORY is automatically assigned the value of 0 (zero) by
the compiler because it appears first in the definition. The compiler then continues to automatically
assign numbers to the enumerated constants, making INSUFFICIENT_DISK_SPACE equal to 1,
LOGIC_ERROR equal to 2, and so on. If you were to approach the same example by using
symbolic constants, your code would look something like this:
#define OUT_OF_MEMORY 0
#define INSUFFICIENT_DISK_SPACE 1
#define LOGIC_ERROR 2
#define FILE_NOT_FOUND 3
Each of the two methods arrives at the same result: four constants assigned numeric values to
represent error codes. Consider the maintenance required, however, if you were to add two
constants to represent the error codes DRIVE_NOT_READY and CORRUPT_FILE. Using the
enumeration constant method, you simply would put these two constants anywhere in the enum
definition. The compiler would generate two unique values for hese constants. Using the symbolic
constant method, you would have to manually assign two new numbers to these constants.
Additionally, you would want to ensure that the numbers you assign to these constants are unique.
Because you don’t have to worry about the actual values, defining your constants using the
enumerated method is easier than using the symbolic constant method. The enumerated method
also helps prevent accidentally reusing the same number for different constants.
Another advantage of using the enumeration constant method is that your programs are more
readable and thus can be understood better by others who might have to update your program later.
Disadvantage of the Enumerated Type
enum types are very problematic to maintain across a number of programming languages which
utilize a User Interface. Incorporating the values of the enum types into the user interface is very
easy and makes the involved component neater, easier to read, even more elegant, and extremely
cheap to implement. The disadvantage is that the enum type is bound to UI controls therefore,
exposing internal information—specifically, type information - to the presentation layer.
Reading List
[Link]
[Link]
[Link]
[Link]
[Link]
Contact Details for Facilitators
Mr. Luyima Alex Cedric
Email: aluyima@[Link] / alace122@[Link]
Phone: +256 772 302 775/+256 708 045 305
Mr. Mugejjera Emmanuel
Email: emugejjera@[Link]
Phone: +256 703 186 705 / +256 772 959 183
Ndejje University in Uganda