Ch3 1
Ch3 1
Enumerators CHAPTER-1
Structures Preprocessor Directives
Unions
What is Enumerators (Enums)?
• An enumerator is a user-defined data type that assigns names to a set of integral constants.
• It makes your code more readable and organized by replacing raw numbers with meaningful names.
• Enums are defined using the enum keyword and can be of different types based on their usage.
1. Improves readability:Enums replace raw numbers with descriptive names, making the code easier to understand.
3. Enhances maintainability:If the values of constants change, you only update them in the enum declaration.
int main() {
displayDifficulty(Medium);
return 0;
}
Types / Usages of Enumerators (enums)
1. Basic Enumerators : A simple list of named constants where each constant is automatically assigned an
integer value starting from 0 (by default).
2. Enumerators with Custom Values : Similar to basic enumerators, but you can manually assign specific
integer values to some or all constants.
3. Enumerators with Arithmetic or Mixed Values : Enumerators where values are assigned using
calculations or combinations of other constants.
4. Anonymous Enumerators : Enumerators without a name, used directly to define constants.
5. Typedef Enumerators : Enumerators defined with a typedef so you can use them without the enum
keyword every time.
6. Bit-Flag Enumerators : Enumerators where each constant represents a power of 2, allowing multiple
constants to be combined using bitwise operations.
Types / Usages of Enumerators (enums)
1. Basic Enumerators: #include <stdio.h>
enum DaysOfWeek {
These are simple enumerations where constants are MONDAY, // 0
assigned integer values automatically starting from 0 TUESDAY, // 1
(default) or from a user-specified value. WEDNESDAY, // 2
THURSDAY, // 3
Syntax : FRIDAY, // 4
enum EnumName { SATURDAY, // 5
SUNDAY // 6
CONSTANT1,
};
CONSTANT2,
CONSTANT3 int main() {
}; enum DaysOfWeek today = WEDNESDAY;
printf("Today is day number: %d\n", today); // Outputs: 2
return 0;
}
Types / Usages of Enumerators (enums)
2. Enumerators with Custom Values #include <stdio.h>
enum ErrorCodes {
You can assign specific integer values to the constants in the SUCCESS = 0,
enum. ERROR_FILE_NOT_FOUND = 404,
If a value isn't specified, it will continue from the previous ERROR_ACCESS_DENIED = 403,
constant's value. ERROR_TIMEOUT = 408
Syntax : };
enum EnumName {
int main() {
CONSTANT1 = 10, enum ErrorCodes error = ERROR_FILE_NOT_FOUND;
CONSTANT2 = 20, printf("Error Code: %d\n", error); // Outputs: 404
CONSTANT3 return 0;
}; }
Real-World Analogy:
HTTP Status Codes: 200 for success, 404 for file not found,
etc.
Types / Usages of Enumerators (enums)
3. Enumerators with Arithmetic or Mixed Values #include <stdio.h>
enum MemorySizes {
Enums allow performing arithmetic operations during BYTE = 1,
declaration, combining constants or offsets. KILOBYTE = BYTE * 1024,
MEGABYTE = KILOBYTE * 1024,
GIGABYTE = MEGABYTE * 1024
Syntax : };
enum EnumName {
int main() {
CONSTANT1 = 10, printf("1 GB = %d bytes\n", GIGABYTE); // Outputs:
CONSTANT2 = CONSTANT1 + 10, 1073741824
CONSTANT3 = CONSTANT2 * 2 return 0;
}; }
Real-World Analogy:
Memory Units: 1 KB = 1024 Bytes, 1 MB = 1024 KB, 1
GB = 1024 MB.
Types / Usages of Enumerators (enums)
4. Anonymous Enumerators #include <stdio.h>
Enums can be defined without a name when their constants int main() {
are to be used directly. enum {
LOW,
MEDIUM,
Syntax : HIGH
};
enum {
CONSTANT1 = 1, int priority = HIGH;
CONSTANT2, printf("Priority level: %d\n", priority); // Outputs: 2
CONSTANT3 return 0;
}; }
Types / Usages of Enumerators (enums)
5. Typedef Enumerators #include <stdio.h>
Enumerators defined with a typedef so you can use them typedef enum {
without the enum keyword every time. SPRING,
. SUMMER,
FALL,
Syntax : WINTER
} Season;
typedef enum {
CONSTANT1, int main() {
CONSTANT2, Season currentSeason = FALL;
CONSTANT3 printf("Current season: %d\n", currentSeason); //
} EnumAlias; Outputs: 2
return 0;
}
Types / Usages of Enumerators (enums)
6. Bit-Flag Enumerators #include <stdio.h>
Bit-Flag Enumerators are a way to use binary values to store enum Permissions {
multiple options in a single variable. This is useful when READ = 1, // 0001
you want to store multiple on/off (true/false) values WRITE = 2, // 0010
efficiently. EXECUTE = 4 // 0100
};
Syntax :
int main() {
enum EnumName { int permissions = READ | WRITE; // Combine using
FLAG1 = 1, // 1 << 0 bitwise OR
FLAG2 = 2, // 1 << 1 printf("Permissions: %d\n", permissions); // Outputs: 3
FLAG3 = 4 // 1 << 2 (0001 | 0010 = 0011)
}; return 0;
}
Structure
What is a Structure in C?
• A structure is a user-defined data type that allows you to group multiple variables of
different data types under one name.
• Structures are particularly useful when you need to represent a complex entity with
various attributes.
• For example, if you need to represent a "Person," you can group attributes like name
(string), age (integer), and height (float) together using a structure.
Declaring a Structure in C
Syntax :
struct StructureName {
dataType member1; Example :
dataType member2; struct Person {
// More members can be added as needed char name[50]; Here:
}; int age; name is a string (character array) to store the
float height; person's name.
}; age is an integer to store the person's age.
height is a float to store the person's height.
Accessing and Using Structures
#include <stdio.h> // Assign values to the members
printf("Enter name: ");
struct Person { scanf("%s", person1.name);
char name[50]; printf("Enter age: ");
int age; scanf("%d", &person1.age);
float height; printf("Enter height: ");
}; scanf("%f", &person1.height);
struct Library {
char name[50];
Example: char books[3][50]; // Array to store 3 book names
Imagine you have a library: };
• Each library has a name and multiple books.
• You create a structure Library that contains an array of books.
Example: Array within a Structure
#include <stdio.h> int main() { // Display library details
// Define a structure for a Library struct Library library; printf("\nLibrary Name: %s\n",
struct Library { // Input library details library.name);
char name[50]; printf("Enter library name: "); printf("Books Available:\n");
char books[3][50]; // Array to store 3 scanf("%s", library.name); for (int i = 0; i < 3; i++) {
book names printf("Book %d: %s\n", i + 1,
}; printf("\nEnter names of 3 books:\n"); library.books[i]);
for (int i = 0; i < 3; i++) { }
printf("Book %d: ", i + 1); return 0;
scanf("%s", library.books[i]); }
}
Structure and Functions
• Structures can be used with functions in C for better modularity and reusability.
• Users can pass a structure to a function, return a structure from a function, or manipulate structure members
within a function.
Key Features:
• No explicit name for the structure. struct {
• Useful for simple and temporary groupings of data. dataType member1;
• Typically used in conjunction with typedef or as part of other structures. dataType member2;
// More members
} variableName;
Example
// Assign values
printf("Enter name: ");
Real-World Example:
#include <stdio.h> scanf("%s", person.name);
You want to quickly
printf("Enter age: ");
group and manage
int main() { scanf("%d", &person.age);
data for a temporary
struct { purpose, such as
char name[50]; // Display values
storing information
int age; printf("Name: %s\n", person.name);
about a one-time
} person; printf("Age: %d\n", person.age);
event (e.g., a single
visitor's details).
return 0;
}
Self-Referential Structures
• A self-referential structure is a structure in programming that includes a pointer (or reference) to another
instance of the same structure.
• Think of it like a train, where each train coach is connected to the next one. Similarly, in programming, one
structure can point to another of the same type, helping us create linked lists, trees, and graphs.These are
commonly used for creating dynamic and linked data structures like linked lists, trees, or graphs.
Key Features:
• Contains a pointer to its own type. struct StructureName {
• Allows the creation of dynamic data structures. dataType member;
• Commonly used in linked data structures. struct StructureName *pointerToSameStructure;
};
Example
#include <stdio.h> // Assign values and link nodes
#include <stdlib.h> node1->data = 10;
node1->next = node2;
node2->data = 20;
// Define a self-referential structure
node2->next = NULL;
struct Node { // Display the list
int data; struct Node *current = node1;
struct Node *next; // Pointer to the next node while (current != NULL) {
}; printf("Data: %d\n", current->data);
int main() { current = current->next;
// Create two nodes }
struct Node *node1 = (struct Node // Free memory
*)malloc(sizeof(struct Node)); free(node1);
free(node2);
struct Node *node2 = (struct Node
*)malloc(sizeof(struct Node)); return 0;
}
Structure Padding
• Structure padding is a mechanism where the compiler adds extra bytes (padding) between structure members to
align them according to the system's word size.
• This ensures better performance by aligning data in memory.
Key Features:
• Added bytes improve data access speed.
• Padding is compiler and architecture-dependent.
• Can lead to wasted memory.
int main() {
printf("Size of struct Padded: %zu bytes\n", Real-World Example:
sizeof(struct Padded)); When working with hardware devices or protocols where data needs to
return 0; align with memory boundaries for efficiency.
}
Example
Avoiding Padding:
You can use the #pragma pack directive to avoid padding (not always recommended for performance reasons):
int main() {
printf("Size of struct Compact: %zu bytes\n", sizeof(struct Compact));
return 0;
}
Pointers in Structures
• A pointer in a structure is a member of a structure that holds the memory address of a specific data type (e.g.,
an integer, a float, a structure, or even another structure).
• Pointers in structures are very useful when dynamically managing memory or linking multiple structures
together. Below, you'll find a detailed explanation, syntax, and example in simple terms.
Initialization of a Union : You can initialize a union when declaring it. However, since all members share the
same memory, initializing one member overwrites any previously stored value.
union UnionName varName = {value}; union Data d1;
d1.i = 42; // Assigning to the integer member
d1.f = 3.14; // Overwrites the integer member
strcpy(d1.str, "Hello"); // Overwrites the float member
You can initialize a union directly during declaration:
Bitfields in Unions : Bitfields are a way to specify that a member of a structure or union should occupy a specific
number of bits in memory, rather than the default size for its type.
This is often used when working with hardware, protocols, or memory optimization.
Syntax :
struct {
unsigned int bit1 : 1; // 1 bit
unsigned int bit2 : 2; // 2 bits
unsigned int bit3 : 3; // 3 bits
}; union Data d1;
d1.i = 42; // Assigning to the integer member
d1.f = 3.14; // Overwrites the integer member
strcpy(d1.str, "Hello"); // Overwrites the float member
Example
union Flags {
struct {
unsigned int option1 : 1;
unsigned int option2 : 1;
unsigned int option3 : 1;
} bits;
unsigned int allOptions;
};
int main() {
union Flags f;
f.bits.option1 = 1; // Enable option1
f.bits.option2 = 0; // Disable option2
f.bits.option3 = 1; // Enable option3
return 0;
}
What is typedef ?
• In simple terms, typedef is a keyword in C that allows you to create a new name (or alias) for an existing data
type.
• Think of it as giving a nickname to a data type to make your code easier to read and understand.