Derived Data Types in C

The derived data types are basically derived out of the fundamental data types. A derived data type won’t typically create a new data type – but would add various new functionalities to the existing ones instead.

In this article, we will take a closer look at the Derived Data Types in C according to the GATE Syllabus for CSE (Computer Science Engineering). Read ahead to know more.

Table of Contents

Uses of Derived Data Types in C

We can derive the derived data types out of the primitive data type by adding some extra relationships to the elements that are available with the primitive data types. We use the derived data types to represent multiple values as well as single values in a program.

Types of Derived Data Types in C

The C language supports a few derived data types. These are:

  • Arrays – The array basically refers to a sequence (ordered sequence) of a finite number of data items from the same data type sharing one common name.
  • Function – A Function in C refers to a self-contained block of single or multiple statements. It has its own specified name.
  • Pointers – The Pointers in C language refer to some special form of variables that one can use for holding other variables’ addresses.
  • Unions – The unions are very similar to the structures. But here, the memory that we allocate to the largest data type gets reused for all the other types present in the group.
  • Structures – A collection of various different types of data type items that get stored in a contagious type of memory allocation is known as structure in C.

*Note – In some of the situations, we can also call the structures and unions to be UDT (User-defined Data Types).

Arrays

An array is one of the most frequently used data types (derived) in the C language. We can form arrays by collecting various primitive data types such as int, float, char, etc. Thus, when we create a collection of these data types and store them in the contiguous memory location, they are known as arrays.

We can create an array with any valid and complete data type. An array type will only get completed when the types and numbers of the array members are implicitly or explicitly specified. We can complete the member types in the same compilation unit or a different one.

An array is typically used to perform various operations on the homogeneous value sets. The size of any given array depends on the total number of elements present in the array, along with the data type present in the array. Every element present in an array belongs to the very same type. For instance,

char a[] = “HEY” /* The declaration of an array a */;

The definition mentioned above would create an array with a total of four characters.

All the elements have a size of 8 bits – about a char object. We determine the size of an array by its initialization. For instance, in this example, the array that we created consists of three explicit types of elements along with a null character. Thus, there are four elements. So, a total of four elements that are about 8 bits each would result in an array that has a total size of about 32 bits. In simple words, this will be equal to a total of 4 bytes.

The allocation of an array is contiguous in the computer memory. It cannot be empty (empty refers to having no members). The arrays are capable of having just one dimension. Thus, if we want to create an array of two dimensions, we have to then declare an array of various arrays (and so on).

For array declaration, it is possible to declare an array with an unknown size. A declaration of this sort is typically known as an incomplete array declaration. It is named so because the size of the array is not at all specified. Here is an example that displays an incomplete declaration type:

int a[];

There must be a specification of the size of an array (that we declare this way) elsewhere in any program that we have with us.

Structures

The structures also form one of the derived data types in the C language. These are capable of forming a collection of various dissimilar data types, such as a float, an int, or even an array of char. Thus, whenever a programmer wants to put various data types together that are not similar to each other, they can utilise a structure.

Thus, a structure type refers to a set of various objects that are sequentially allocated and non-empty. These objects are known as members. Thus, structures would let a person group heterogeneous types of data together. Now unlike arrays, all the elements that constitute a structure do not need to be of the very same data type. Added to this, one can access all the elements of a typical structure by their names and not by subscripts. For instance, the example mentioned below would be used to declare the student structure, which has two structure variables (elsa and vin) of the student structure type. Here is how it would look:

struct student { char names[50]; int ages; int studnumber; };

struct student vin, elsa;

The members present in a structure can be of any type, but an incomplete type would be an exception, for instance, a function type or the void type. A typical structure can consist of pointers for objects of its type. On the other hand, it cannot have an object of its type in the form of a member. In case this happens, the object would then be of an incomplete type.

For instance,

struct student {

char names[50];

struct student point; /* The data type here will be invalid. */

int *f();

};

The example mentioned below, however, will be invalid in a program:

struct student {

char names[50];

struct student *point;/* The member can consist of a pointer to the student structure. */

int (*f)(); /* It is a pointer to a function that returns int */

};

There must be a unique name for a declared structure member within any structure. However, note that we can use it in another unnested or even nested structure, or even namespaces for referring to a different type of object.

For instance,

struct {

int a;

struct {

int a; /* The ‘a’ here would refer to a different object as compared to the previous ‘a’ */

};

};

A compiler would basically assign storage for all the structure members in the exact order of the member declaration. It has an increasing memory address for all the members occurring subsequently. Here, the very first member happens to begin at the structure’s starting address itself. Then the alignment of the subsequent members occurs according to the alignment unit. Now, it may differ on the basis of the sizes of the members present in the structure.

A typical structure may consist of unused bits (padding) so that all the members of an array of all such structures are aligned properly. Thus, the size of a structure becomes equal to the total storage necessary for all of its members in addition to any of the padded spaces required for meeting the requirements of alignment.

Unions

The union is also a derived form of data type in the C language, which is quite similar to the structure. But here, the amount of memory that it uses is actually equal to the size of that union member contained in it, which takes up the maximum storage space.

The union type is responsible for storing objects of various different types in the very same location of the memory. It means that in any program, various different types of union members would be able to occupy the very same location at different times. A union declaration includes all of the members present in a union. It lists all the possible object types that a union is capable of holding. A typical union is capable of holding any one of the members at any given time. The subsequent assignment of any other member to the very same union would lead to the overwriting of the existing object present in the same specified storage area.

We can name the unions using any valid identifier. Keep in mind that we cannot declare an empty union, and a union is incapable of containing an instance of itself. The union members can’t have a function, the void, or even an incomplete type, but the unions can consist of pointers to the unions of their own type.

In simpler terms, we can view unions as single objects that are capable of representing various objects of different types in the same location at different times. A union would let anyone use those objects whose size and type can easily change with the progress of the program – even if you don’t use some machine-dependent type of constructions. This concept is also known as a variant record in some other languages.

The syntax that we use to define the unions is similar to that of the syntax used for writing the structures. Here, the definition of every union type would lead to the creation of a new type. We must use unique names for all the union members, but these names can also be duplicated in various other unnested or nested unions as well as namespaces.

For instance,

union {

int a;

union {

int a; /* The ‘a’ used here would refer to an entirely different object as compared to the previously used ‘a’ */

};

};

Here, the size of any union would be equal to the total storage necessary for the largest member in the union and also, any padding required for meeting the requirements of alignment.

For instance, if we have a union that consists of a float, an array of 5 char, and an array of 5 integers, then the union storage space would be equal to a total of 20 bytes for a 64-bit compiler type.

Function

The function type is basically used to define a function that would return any value of specified types. Whenever a function doesn’t return a value, it must be declared in the form of a function returning void. We can do this as follows:

void function ();

The example mentioned below contains the data type for its functions as the function returning int. Here is how the code will be:

int add()

{

int x=10, y=10, z;

z=x+y;

return z;

}

How do we calculate the size of any given function?

Here is how we calculate the size of any available function:

Size of a function = Total size of all the local variables that have been declared in the function + the size of the global variables that have been used in the function + the size of all of the parameters + the size of the returned value when it’s an address.

For instance, here is how we calculate the size of any add function:

int add()

{

int x=10,y=10,z;

z=x+y;

return z;

}

Thus, the answer that we would get here is about 12 bytes for a 64-bit type of compiler.

Pointers

The pointers are also derived data types in the C language. The size that a pointer takes up in the memory is always pretty much fixed. Still, the type of pointer that we get depends entirely on the type of that element for which it stores the address.

Thus, it’s like if the pointer stores the address of an available integer, then the pointer type would be equal to the integer point. On the other hand, if the pointer happens to store an array’s address, then the pointer type would be equal to the array pointer.

In simpler words, we can define pointers in C language as the variables that are capable of storing the address of any other variable in them. The pointers in C can also hold the address of any type stored in them, be it the FLOAT, INTEGER, ARRAY, STRING, FUNCTION, and STRUCTURE.

Practice Problems on Derived Data Types in C

1. What would be the output obtained out of the program mentioned below:

#include<stdio.h>int main(){

int x=0;

int scores[5];

clrscr();

scores[0]=50;

scores[1]=60;

scores[2]=75;

scores[3]=40;

scores[4]=85;

for(x=0;x<5;x++){

printf(“%d \n”,scores[x]);

}

return 0;

}

A. 60 50 45 70 85

B. 60 50 75 40 95

C. 50 60 75 40 85

D. 50 60 95 70 65

Answer – C. 50 60 75 40 85

2. What would be the output obtained out of the program mentioned below?

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

struct Student {

char enrollment[50];

int stud_id;

float fee;

} student1;

int main() {

strcpy(student1.enrollment, “Niloufer”);

student1.stud_id = 1779;

student1.fee = 3900;

printf(“Enrollment: %s\n”, student1.enrollment);

printf(“Student ID: %d\n”, student1.stud_id);

printf(“Fee: %.2f”, student1.fee);

return 0;

}

A. Enrollment: Niloufer Student

Student IDs: 1779

Fee: 3900.00

B. Enrollment: Niloufer

Student ID: 1779

Fee: 3900.00

C. Enrollment: Niloufer Student

Student IDs: 1779

Fees: 3900.00

D. Enrollment: Niloufer

Student IDs: 1779

Student Fees: 3900.00

Answer – B. Enrollment: Niloufer

Student ID: 1779

Fee: 3900.00


FAQs

Why do we need to create derived data types in C when we already have the primitive data types?

We can derive the derived data types out of the primitive data type when we add some extra relationships to the elements that are available with the primitive data types. We use the derived data types to represent multiple values as well as single values in a program.

2. What is the difference between the arrays and structures?

The allocation of an array is contiguous in the computer memory. It cannot be empty (empty refers to having no members). The arrays are capable of having just one dimension. Thus, if we want to create an array of two dimensions, we have to then declare an array of various arrays (and so on). Unlike arrays, all the elements that constitute a structure do not need to be of the very same data type. Added to this, one can access all the elements of a typical structure by their names, and not by subscripts.

Keep learning and stay tuned to get the latest updates on the GATE Exam along with Eligibility Criteria, GATE Syllabus for CSE (Computer Science Engineering), GATE CSE Notes, GATE CSE Question Paper, and more.

Also Explore,

Leave a Comment

Your Mobile number and Email id will not be published.

*

*