1. Choose the correct option:
(i) Which of the following cannot be a variable name in C?
(a) Volatile
(b) True
(c) Friend
(d) Export
(ii) What is the output of the following segment of C code?
#include<stdio.h>
{
printf(5 + “Brahmaputra”);
return 0;
}
(a) 5 + Brahmaputra
(b) aputra
(c) Brahmaputra
(d) Compile Time Error
(iii) Which of the following is not a logical operator?
(a) |
(b) !
(c) &&
(d) ||
(iv) Assume that a character takes 1 byte. Output of following program?
#include<stdio.h>
int main()
{
char str[20]=”ASTU”;
printf(“%d”, sizeof(str));
return 0;
}
(a) 4
(b) 8
(c) 16
(d) 29
// The correct answer is : 20
(v) #include<stdio.h>
main()
{
printf(“Assam”);
main();
}
(a) Wrong statement
(b) It will keep on printing Assam
(c) It will print Assam once
(d) None of these
(vi) What will this program print?
main()
{
int i=2;
{
int i=4, j=5;
printf(“%d %d”, i,j);
}
printf(“%d %d”, i,j);
}
(a) 4525
(b) 2525
(c) 4545
(d) 2554
Note: The program would not compile successfully due to the out-of-scope variable j. It will result in a compilation error.
(vii) Which of the following operators can be applied on structure variables?
(a) Equality comparison(==)
(b) Assignment(=)
(c) Both of the above
(d) None of the above
(viii) Suppose the pointer variable has p address 1000, and that p is declared to have type int*, and an int is 4 bytes long. What address is represented by expression p+3?
(a) 1003
(b) 1006
(c) 1009
(d) 1012
(ix) What will be the output of the following C code?
#include<stdio.h>
int main() {
int x=10,*ptr;
ptr=&x;
*ptr=20;
printf(“%d”,x);
}
(a) 10
(b) 20
(c) Any garbage value
(d) Compile time error
(x) Which is the correct syntax to declare a file pointer in C?
(a) File *file_pointer
(b) FILE *file_pointer
(c) File file_pointer;
(d) FILE file_pointer
2. (a) What is header file? Why they are needed?
Ans: A header file is a file that containing declarations of functions, variables, constants, macros and other elements that can be used in a program. Header files are used to provide information to the compiler about the names and types of these elements, allowing the compiler to properly interpret and validate the code in the source files that include the header.
Header files have extension “.h” (e.g., stdio.h) and are included in C programs using the #include preprocessor directive. Commonly used C header files include <stdio.h> for input/output functions, <stdlib.h> for memory allocation and other utility functions, <math.h> for mathematical functions etc.
Header files in C are essential for organizing code, providing function prototypes and shared declarations, promoting modularity, and facilitating code reuse. They are essential in large projects and contribute to writing clean and maintainable C programs.
Header files are used in C so that we don’t have to write the code for every single thing. It helps to reduce the complexity and number of lines of code. It also gives us the benefit of reusing the functions that are declared in header files to different files and including a header file is way easier than writing the implementations. By using a header file, we keep the program precise and focused, which makes it manageable.
(b) Why Indentation and documentation is essential in a program?
Ans: Indentation and documentation are essential aspects of writing maintainable and readable code in a programming language. They contribute significantly to the overall clarity, understandability, and maintainability of a program. Indentation and documentation are crucial for maintaining clean, understandable, and maintainable code.
Indentation and documentation are essential elements in programming for several reasons:
Indentation:
Code Readability: Indentation improves code readability by visually representing the structure of code. This makes it easier for programmers to read and understand the logical flow of the program. Indentation helps programmers quickly understand the flow and hierarchy of statements within loops, conditionals and functions.
Code Structure: Indentation helps to visually represent the hierarchical structure of the code, especially in languages where the scope of control structures (like loops and conditionals) is defined by indentation. This aids in quickly identifying the beginning and end of code blocks.
Maintenance: Well-intended code is easier to maintain. When code needs modification or debugging, clear indentation makes it simple for developers to identify code blocks and understand how changes may affect the program.
Debugging: Proper indentation can make it easier to identify syntactical errors and logical issues during debugging. It allows programmers to trace the execution flow and spot potential problems more quickly.
Documentation:
Code Understanding: Documentation provides comments and explanations within the code, making it easier for other programmers (or even the original author after some time) to understand the purpose, functionality, and usage of specific code sections.
Maintenance: When revisiting code after a period of time or when collaborating with others, documentation becomes invaluable. It helps maintainers understand the intent behind the code and make modifications without unintended side effects.
Code Reviews: During code reviews, documentation provides context for reviewers, allowing them to assess the correctness and quality of the code more effectively.
(c) What is program? What are the different steps of program development?
Ans: A program is a set of instructions that a computer follows in order to perform a particular task. Programs are created using specific programming languages such as C, C++, Java, Python etc. A program is a set of instructions that process input, manipulate data, and output a result. For example, Microsoft Word is a word processing program that allows users to create and write documents.
Program development is the process of creating programs. A program development process consists of various steps that are followed to develop a computer program. These steps are followed in a sequence in order to develop a successful and beneficial computer program.
Following is a brief description of the program development process:
Analyze the problem: In this step, a programmer must figure out the problem, and then decide how to resolve the problem.
Design the program: The programmer designs an algorithm to help visual possible alternatives in a program also. A flow chart is important to use during this step of the program development. This is a visual diagram of the flow containing the program. This step will help to break down the problem.
Code the program: This is using the language of programming to write the lines of code. The code is called the listing or the source code.
Debug the program: Debugging is a process of detecting, locating and correcting the bugs in a program. The bugs are important to find because this is known as errors in a program.
Formalize the solution: One must run the program to make sure there are no syntax and logic errors. Syntax are grammatical errors and logic errors are incorrect results.
Document and maintain the program: This step is the final step of gathering everything together. When the program is finalized, its documentation is prepared.
(d) What is algorithm? What are its various characteristics?
Ans: An algorithm is a well-defined set of steps used to perform a specific task. It is a finite sequence of instructions to solve a problem or carrying out a computation. Algorithm describes how to solve a problem.
It is a step-by-step procedure or set of rules designed to perform a specific task or solve a particular problem. Algorithm refers to the set of finite instructions to be followed in calculations or other problem-solving operations.

Characteristics of Algorithm:
An algorithm should have the following characteristics:
Input: An algorithm requires some input values. Algorithms take input which is the data or information they operate on. The input can vary from problem to problem and is essential for the algorithm’s operation.
Output: There should be at least one output produced. Algorithm produces output which is the solutions or result to the problem. The output should be in a format that is understandable and useful to the user.
Definiteness: Each step of an algorithm should be well-defined, clear and simple. Algorithm should be clear and unambiguous. There should be no ambiguity in how to execute each step.
Finiteness: Here, finiteness means that the algorithm should contain a limited number of instructions. The number of steps in an algorithm is finite. Algorithms should terminate after a finite number of steps. They should not run indefinitely. This ensures that the algorithm’s execution will eventually complete.
Effectiveness: An algorithm must be effective in that it can solve the problem or complete the task for any valid input. Every instruction must be basic i.e., simple instructions.
Feasible: Algorithm must be capable of execution within a reasonable amount of time and resources. The algorithm must be simple, generic and practical such that it can be executed with the available resources. They shouldn’t be overly complex and inefficient.
(e) What is flow chart? Describe different symbols used in it.
Ans: A flowchart is a graphical representation of a process or algorithm. It uses different shapes and arrows to illustrate the steps of a process and the flow of data. Flowcharts are commonly used in software development, business processes, problem-solving and various other fields to visually depict the structure and logic of a process.
A flowchart describes the control flow, the order in which the various program steps are executed within any computer program or module. Flowchart is basically a pictorial or diagrammatic representation of a sequence of logical steps of a program. It uses various symbols to show the operations and decisions to be followed in a program. Flowcharts are a visual representation that helps in understanding the structure and logic of a process or algorithm. Flowcharts are widely used in various fields for process documentation, analysis, and communication.
Flowchart Symbols:
To express different operations in the flowchart various standard symbols are used. All symbols are connected among themselves in order to show the flow of information and processing.
Terminator: This is the oval shape in the process flow chart. Represents the beginning or end of a process. The terminal symbol identifies the start and end of the flowchart.
Process: Processes are represented by rectangles. Represents a task or operation in the algorithm.
Decision: The decision box is represented by a diamond shape. Represents a decision point in the algorithm. Diamond shapes are used to check any condition. A yes/no/true/false decision.
Flow lines or Arrow: Arrows indicate the flow or direction of the process. Represents the flow from one component to the next.
Input/Output: Input/output represented byparallelogram. Represents input or output operations, such as reading from or writing to a file, or getting user input.
Data storage: Represents data storage or a database. This specifies where data or information is stored.
Connector: Connectors are represented by circles. Indicates a connection between different parts of the flowchart or between pages in a multi-page flowchart.
Annotations: Annotations represent comments or remarks about the flowchart. Like comments found in high-level programming languages, they have no effect on the interpretation or behavior of the flowchart.
3 (a) Explain the working procedure of do while loop.
Ans: The do-while loop is a control flow structure that executes a block of code repeatedly as long as a specified condition is true. Unlike the while loop, the do-while loop guarantees that the block of code is executed at least once, as the condition is checked after the execution of the block. The key characteristic of a do-while loop is that the loop body is executed at least once, even if the condition is false initially. do-while loop is suitable when we want to ensure that the loop body executes at least once, regardless of the initial condition.
Here is the general syntax of a do-while loop:
do {
// Statements to be executed
} while (condition);
The working procedure of the do-while loop can be explained in the following steps:
Execute the Loop Body: The statements within the do block are executed first, without checking the condition. This means that the block of code is executed at least once, regardless of whether the condition is initially true or false.
Check the Condition: After executing the loop body, the condition specified in the while statement is checked.
Repeat if True: If the condition is true, the loop body is executed again, and the process repeats. After each iteration, the condition is re-evaluated.
Exit the Loop: Once the condition becomes false, the loop exits, and the program continues with the next statement after the do-while loop.
(b) Write a C program to find the largest among three given numbers, by applying conditional operator.
Ans: Program to find the largest among three given numbers, by applying conditional operator:
#include <stdio.h>
int main() {
// Input three numbers
int num1, num2, num3, largest;
printf(“Enter three numbers: “);
scanf(“%d %d %d”, &num1, &num2, &num3);
// Find the largest using the conditional operator
largest = (num1 > num2)? ((num1 > num3)? num1: num3): ((num2 > num3)? num2: num3);
// Display the result
printf(“The largest number is: %d”, largest);
return 0;
}
OR
#include <stdio.h>
int main() {
// Input three numbers
int num1, num2, num3, largest;
printf(“Enter three numbers: “);
scanf(“%d %d %d”, &num1, &num2, &num3);
// Find the largest using the conditional operator
largest = num1 > num2 ? num1: num2
largest=largest>num3: largest: num3
// Display the result
printf(“The largest number is: %d”, largest);
return 0;
}
(c) Why break is essential in switch statement? What is the significant of default statement?
Ans: Break statement is essential for controlling the flow of execution within the switch statement. The break statement is used to terminate the execution of the switch block once a matching case is found. Without the break statement, execution would continue to the next case regardless of whether the condition is match or not. The break statement ensures that once a matching case is found and executed, the control flow exits the switch statement. Break is crucial to terminate the execution of a switch statement after a matching case.
#include <stdio.h>
int main() {
int choice = 2;
switch (choice) {
case 1:
printf(“You chose option 1”);
break;
case 2:
printf(“You chose option 2”);
break;
case 3:
printf(“You chose option 3”);
break;
default:
printf(“Invalid choice\n”);
break;
}
return 0;
}
In this example, the value of choice is 2, the program will print “You chose option 2” and then exit the switch statement due to the break statement. Without the break statement the program would continue to execute the code for subsequent cases.
The default statement is optional, and it is executed when none of the specified case values matches the switch expression. It is similar to the else statement in an if-else construct. Including a default case is a good practice to handle unexpected or undefined values. If no case matches and there is no default statement, the switch statement does nothing.
(d) What is an array? How an array is declared? Write a program in C to display the largest and smallest element in an integer array.
Ans: An array is a collection of similar data elements stored at contiguous memory locations. This data type is useful when a group of elements are to be represented by a common name. An array is used to store a group of data items that belong to the same data type. An array is a group of elements that share a common name, and is differentiated from one another by their positions within the array. An array is also defined as a collection of homogeneous data.
Declaration of Array:
An array must be declared before they are used in the program. The general form of array declaration is:
Syntax:
data_type array_name[size];
The data_type specifies the type of element that will be contained in the array, such as int, float, or char and the size indicate the maximum number of elements that can be stored inside the array.
Example:
int mark[5];
Here, int is the data_type, mark is the array_name, and 5 is the size.
Program in C to display the largest and smallest element in an integer array:


Output:

4. (a) What are function prototypes? Is function prototype mandatory for every user defined function in C? Justify your answer.
Ans: A function prototype is a declaration of a function that tells the compiler about the function’s name, return type, and the types of its parameters. It provides essential information to the compiler before the actual implementation (function definition). The purpose of a function prototype is to inform the compiler about the function’s signature, allowing it to perform type checking and generate appropriate code for function calls.
A function prototype typically takes the form:
return_type function_name(parameter1_type, parameter2_type, …);
No, a function prototype is not strictly mandatory for every user-defined function, but it is considered good practice to include them. If a function is defined before it is called in the program, the compiler can infer its prototypes based on the definition. While the prototype is not strictly required, it helps ensure proper type checking and enhances code readability.
Reasons why using function prototypes is recommended:
Type Checking: Function prototypes enable the compiler to perform type checking. If the function is used before its definition or if the definition doesn’t match the prototype, the compiler can issue warnings or errors.
Code Readability: Prototypes improve code readability by providing a clear and concise description of the function’s interface. This helps other programmers understand how to use the function correctly.
Modularity: Prototypes facilitate modularity in code. They allow us to declare functions in header files, which can be included in multiple source files. This promotes code organization and reusability.
(b) What are the advantages of using function in a program?
Ans: By using function, large and difficult program can be divided into sub programs and solved. When we want to perform some tasks repeatedly or some code is to be used more than one at different place in the program, then function avoids this repetition or rewritten over and over.
There are many advantages of using functions in a program they are:
- A large program becomes difficult to understand. By using function, it becomes easier. Breaking the code in smaller Functions keeps the program organized, easy to understand and makes it reusable.
- Dividing a large program into various functions makes the program easier to design and debug.
- Logical clarity of the program is increased hence programming becomes simpler.
- It reduces the complexity of a program and gives it a modular structure.
- It makes the program more structured, more readable. Use of functions enhances the readability of a program.
- The size of the program can be reduced by calling and using functions at appropriate places.
- It becomes easier to locate and separate a faulty function for further study.
- By using functions, we can avoid rewriting the same block of codes at two or more locations in a program. We can easily call and use functions whenever they are required.
(c) Write a C program to find the factorial of a given number using recursion method.
Ans: Program to find the factorial of a given number using recursion method.
#include<stdio.h>
long int fact(int n);
int main( )
{
int num;
printf(“\n Enter a number: ”);
scanf(“%d”,&num);
printf(“\nFactorial of %d is :%ld”,num,fact(num));
getch();
return 0;
}
long int fact(int n)
{
if (n<=1)
return 1;
else
return (n*fact(n-1));
}
Output:
Enter a number: 4
Factorial of 4 is: 24
(d) Why NULL character is important in terms of string?
Ans: The NULL character, represented by ‘\0’ in C, is crucial in terms of strings because it serves as the string termination character. The NULL character is fundamental for proper string handling in C, helping functions determine the end of a string and facilitating operations like printing, copying, and comparing strings.
NULL character is important in terms of strings for several reasons:
String Termination: In C, strings are represented as arrays of characters. The NULL character is used to indicate the end of a string. When the compiler encounters a NULL character in a character array, it treats the preceding characters as part of the string, and the string is effectively terminated.
String Length determination: Since the NULL character marks the end of a string, function strlen()
in the <string.h> library use the presence of the NULL character to determine the length of the string. The function counts characters from the beginning of the string until it encounters the NULL character.
String Printing: Functions like printf() use the NULL character to know where the string ends. When we use %s in printf(), it starts printing characters from the beginning of the string until it encounters the NULL character.
String Comparison: Functions like strcmp() (string comparison) also rely on the NULL character to compare strings. The comparison stops as soon as a difference is encountered or the NULL character is reached.
(e) What is the difference between getch() and getche() ? Give examles.
Ans: In C programming, getch() and getche() are functions that are used for reading a character from the console, but they behave differently.
getch():
- getch() is a function defined in the <conio.h> library, which is not a standard C library and is often used in older compilers or DOS-based environments.
- It reads a single character from the keyboard without echoing it to the screen, meaning the entered character is not displayed on the screen.
- It does not wait for the user to press Enter; the input is immediately processed.
Example:
#include <stdio.h>
#include <conio.h> // For getch()
int main() {
char ch;
printf(“Enter a character: “);
ch = getch(); // Reads a character without echoing
printf(“\nYou entered: %c\n”, ch);
return 0;
}
getche():
- getche() is also defined in the <conio.h> header.
- It reads a single character from the keyboard and echoes it to the screen, allowing the user to see the entered character.
- It displays the entered character on the console.
Example:
#include <stdio.h>
#include <conio.h> // For getche()
int main() {
char ch;
printf(“Enter a character: “);
ch = getche(); // Reads a character with echoing
printf(“\nYou entered: %c\n”, ch);
return 0;
}
5. (a) Write a C program to subtract two matrices.
Ans:
#include<stdio.h>
#include<conio.h>
int main()
{
int a[3][3], b[3][3], Sub[3][3], i, j;
printf(“Enter First 3*3 Matrix Elements: “);
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
scanf(“%d”, &a[i][j]);
}
printf(“Enter Second 3*3 Matrix Elements: “);
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
scanf(“%d”, &b[i][j]);
}
printf(“Subtracting two matrices…..”):
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
Sub[i][j] = a[i][j] – b[i][j];
}
printf(“\nThe Subtraction Result is:\n”);
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf(“%d “, Sub[i][j]);
printf(“\n”);
}
getch();
return 0;
}
(b) Give the advantages of pointers in C. Is there any relationship between an array name and a pointer? Justify your answer.
Ans:
Advantages of pointer:
Dynamic Memory Allocation: Pointers allow dynamic memory allocation using functions like malloc(), and free(). This enables the efficient memory utilization during program execution.
Efficient parameter passing: Pointers can be used to pass addresses of variables to functions, allowing functions to modify the original data directly. This can be more efficient than passing data by value, especially for large data structures.
Efficient String Handling: Strings in C are typically represented as arrays of characters, and pointers simplify string operations, making them more efficient and flexible.
Efficient File handling: Pointers are useful when working with files, enabling the efficient movement and manipulation of data within a file
Efficient Data Structures: Pointers are essential for implementing advanced data structures like linked lists, trees, and graphs. They provide a flexible way to create and manipulate complex data structures.
Relationship Between Array Name and Pointer:
In C, there is a close relationship between array names and pointers. The name of the array is a pointer to the first element of the array. That means it holds the address of the very first element of the array. An array name is a constant pointer to the first element of the array. Therefore, an array name and a pointer have a close relationship.
Here are some points that illustrates the relationship:
Array Name as a Pointer: the array name, when used in an expression, is treated as a pointer to the first element of the array.
int numbers[5] = {1, 2, 3, 4, 5};
int *ptr = numbers; // Equivalent to &numbers[0]
Here, the array name numbers is used as a pointer to the first element of the array.
Pointer Arithmetic: Array names can be used in pointer arithmetic. Array subscript notation (arr[i]) is equivalent to pointer arithmetic (*(arr+i)). This means we can use pointers to traverse arrays.
int numbers[5] = {1, 2, 3, 4, 5};
int *ptr = numbers;
printf(“%d\n”, numbers[2]); // Output: 3
printf(“%d\n”, *(ptr + 2)); // Output: 3
Passing Arrays to Functions: When an array is passed as a parameter to a function, it is implicitly converted to a pointer to the first element.
void printArray(int arr[]) {
// arr is treated as a pointer to the first element
}
(c) What does the variable ‘a’ specifies in the following declarations in c?
- float *a;
- int *a[10];
Ans:
(i) float *a;
This declaration indicates that a is a pointer to a float. It means that a can store the memory address of a variable of type float. This pointer can be used to dynamically allocate memory for a single float or point to an existing float variable.
Example:
float *a; // Declaring a pointer to float
float x = 3.14;
a = &x; // Assigning the address of x to the pointer
(ii) int *a[10];
This declaration indicates that a is an array of 10 pointers to int. It means that a is capable of storing the addresses of 10 different int variables. Each element of the array a is a pointer to an int.
Example:
int x = 42;
int y = 73;
int *a[10]; // Declaring an array of 10 pointers to int
a[0] = &x; // Assigning the address of x to the first element of the array
a[1] = &y; // Assigning the address of y to the second element of the array
(d) What do you mean by dynamic memory allocation? How it is implemented in C program?
Ans: The process of allocating and deallocating (freeing) memory at the time of execution of a program (at runtime) is called dynamic memory allocation. Dynamic memory allocation refers to the process of allocating memory at runtime rather than at compile time. This allows the program to request memory of a certain size during its execution, enabling flexibility in handling varying amounts of data.
Dynamic memory allocation is useful when the size of data structures is not known at compile time or when memory needs to be managed more flexibly during program execution. Dynamic memory allocation is facilitated by the use of functions like malloc(), calloc(), realloc() and free() in C.
Here’s a brief overview of the memory allocation and deallocation functions:
malloc() function:
The malloc or memory allocation function is used to allocate a block of memory of the specified size (in bytes). It returns a pointer to the first byte of allocated space. The type of the pointer it returns is void, which can be cast into a pointer of any type. It returns NULL, if there is not enough memory available. The malloc() function does not initialize memory at execution time, so it has garbage value initially.
Syntax:
ptr=(cast_type*)malloc(size_in_bytes)
Example:
int *x;
x=(int*)malloc(sizeof(int));
The above statement allocates 2 bytes of main memory and returns the address of the memory allocated which is stored in x. The (int *) before the malloc function casts the integer type on malloc, hence malloc returns a pointer to the integer.
calloc() function:
The calloc or contiguous allocation function works similar to malloc() function except for the fact that it requires two parameters or arguments as against one parameter needed by malloc(). It allocates multiple block of requested memory.
Syntax:
ptr=(cast_type*)calloc(n, size_in_bytes);
Here, n is the number of blocks and size_in_bytes specifies size of each block
calloc() initializes each block with a default value 0. It returns NULL, if there is not enough memory available.
Example:
float *y;
y=(float *) calloc(5, sizeof(float));
This statement allocates contiguous space in memory for 5 elements of type float.
realloc() function:
The realloc or re-allocation function is used to resize the size of memory block, which is already allocated. In short, it changes the memory size. This function is used to expand or shrink the allocated memory block. It is useful in two applications:
1. If the allocated memory block is insufficient for current application.
2. If the allocated memory is much more than what is required by the current application
Syntax:
ptr=realloc(ptr, new_size);
Here, ptr is reallocated with a new size, new_size
free() function:
Just as memory can be dynamically allocated during runtime, it can also be de-allocated when not needed. When an element is no longer required, the memory allocated to it must be freed so that it is available for future use. This is done by the function free(). It helps to reduce wastage of memory by freeing it.
Syntax:
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.
6. (a) List out the advantages and disadvantages of union over structure in C.
Ans: In C programming, both unions and structures are used to group related data under a single name, but they have distinct characteristics.
Here are the advantages and disadvantages of using unions compared to structures:
Advantages of Unions:
Memory Efficiency:
Unions are more memory-efficient than structures because they share the same memory space for all their members. Only one member is active at a time, and the size of the union is determined by the largest member.
Space Savings:
Unions are useful when we need to represent a data structure where only one of several members is active or relevant at a given time. This can result in significant space savings compared to using a structure with all members present.
Versatility:
Unions provide a versatile way to represent different types of data in the same memory location. This is especially useful when dealing with situations where only one type of data is relevant at any given time.
Bit-Level Manipulation:
Unions can be used for bit-level manipulation and to create flexible data structures for tasks like encoding and decoding data.
Disadvantages of Unions:
Lack of Type Safety:
Unions do not provide type safety. Since different members share the same memory space, it is the programmer’s responsibility to ensure that the correct member is accessed and that the data is interpreted correctly.
Limited Information:
Unions do not store information about which member is currently active. The programmer must keep track of this information externally.
Initialization Issues:
Initializing a union with one member and later accessing another member without proper updates can lead to undefined behavior. Care must be taken to ensure that the union is used correctly.
Limited Use Cases:
Unions are most suitable for scenarios where only one member is relevant at a time. In cases where multiple members need to be simultaneously active or when type safety is crucial, structures may be more appropriate.
Example illustrating Structure and Union:
#include <stdio.h>
// Structure
struct Point {
int x;
int y;
};
// Union
union Data {
int intValue;
float floatValue;
};
int main() {
// Structure example
struct Point point1 = {3, 4};
printf(“Point coordinates: (%d, %d)\n”, point1.x, point1.y);
// Union example
union Data data;
data.intValue = 42;
printf(“Integer value: %d\n”, data.intValue);
data.floatValue = 3.14;
printf(“Float value: %f\n”, data.floatValue);
return 0;
}
(b) Can a structure be declared within a structure? Give appropriate examples to support your answer.
Ans: Yes, in C programming, a structure can be declared within another structure. This concept is known as a nested structure. A nested structure allows us to organize related data in a hierarchical manner. Nested structures are useful when we need to represent complex relationships between different pieces of data. They provide a way to organize and access related information in a structured manner. We can extend the nesting to more levels based on the complexity of data structure requirements.
Here’s an example to illustrate the declaration and use of a nested structure:
#include <stdio.h>
// Outer structure
struct Date {
int day;
int month;
int year;
};
// Inner structure
struct Student {
int rollNumber;
char name[50];
struct Date birthDate; // Nested structure
};
int main() {
// Declare and initialize a structure variable
struct Student student1 = {
.rollNumber = 101,
.name = “John Doe”,
.birthDate = {25, 12, 2000} // Initializing the nested structure
};
// Accessing members of the nested structure
printf(“Student Information:\n”);
printf(“Roll Number: %d\n”, student1.rollNumber);
printf(“Name: %s\n”, student1.name);
printf(“Birth Date: %d/%d/%d\n”, student1.birthDate.day, student1.birthDate.month, student1.birthDate.year);
return 0;
}
In this example:
- The Date structure represents a date with day, month, and year components.
- The Student structure includes an instance of the Date structure as a member. This creates a nested or embedded structure within the Student structure.
- In the main function, a Student structure variable (student1) is declared and initialized, including the nested Date structure.
(c) What are the storage class for C variables? What is their significance? Explain with examples.
Ans: Storage classes are used to describe the features of a variable. Every variable in C has two attributes, type and storage class. Type refers to the data type of a variable, and storage class determines the scope or visibility, life time, memory location and initial value of a variable. In our programs, we didn’t mention storage class of the variables used. This is because of the fact that if the storage class is not given for a variable in its declaration, then the compiler will assume a storage class as the default.
A storage class describes the following:
- The location where the variable would be stored.
- The default initial value of the variable if it is not initialized
- The scope of the variable
- The life time of the variable, i.e. for how long will the variable exist.
Syntax of declaring storage classes is:
storage_class data_type variable_name;
There are four types of storage classes in C:
1. auto (Automatic) storage class
2. Static storage class
3. Register storage class
4. Extern (External) storage class
Each storage class has its own significance.
Auto (Automatic) Storage Class:
The auto storage class is the default storage class for local variables. The variables defined using automatic storage class are called local variables because they are local to a function where they are defined. By default, they are assigned garbage value by the compiler. The keyword used to declare automatic storage class variable is auto.
Example:
#include <stdio.h>
int main() {
auto int num = 10; // ‘auto’ is optional, as it is the default storage class
printf(“Value of num: %d\n”, num);
return 0;
}
static Storage Class:
The static storage class is used to declare variables that retain their values between function calls. Static variables are initialized only once, and their values persist throughout the program’s execution. The static storage class instructs the compiler to keep the variable value until the end of program. These variables retain their values throughout the life-time of the program. Like automatic variables, static variables are also local to the function, in which they are defined.
The keyword used to declare static storage class variable is static.
Example:
#include <stdio.h>
int main() {
incrementStatic();
incrementStatic();
incrementStatic();
return 0;
}
void incrementStatic() {
static int counter = 0; // ‘static’ retains the value between function calls
counter++;
printf(“Static counter: %d\n”, counter);
}
register Storage Class:
The register storage class is used to suggest the compiler to store the variable in a CPU register for faster access. A value stored in CPU register can always be accessed faster than that of variable stored in memory. Frequently accessed variables are kept in register. Therefore, if a variable is used at many places in a program, it is better to declare its storage class as register.
Example:
#include <stdio.h>
int main() {
register int count = 0; // ‘register’ suggests the use of a register for faster access
while (count < 5) {
printf(“%d “, count);
count++;
}
return 0;
}
extern Storage Class:
The extern storage class is used to declare variables that are defined in another file. It is often used when we want to use a variable that is defined in another source file. External storage class informs the compiler that the variable defined as extern is defined elsewhere in any program. We use external variable for giving a reference of any global variable which have been already defined.
The external storage class is used when we have global variables which are shared between two or more files. These variables are accessible throughout the program.
Example:
// File: file1.c
int globalVar = 100;
// File: file2.c
#include <stdio.h>
extern int globalVar; // ‘extern’ declares the variable defined in another file
int main() {
printf(“Value of globalVar: %d\n”, globalVar);
return 0;
}
7. (a) Write a function which accepts an array of size n containing integer values and returns average of all values. Call the function from main program.
Ans:
#include<stdio.h>
int avg(int a[],int n);
int main()
{
int a[10], n, i, avrg;
printf(“\nEnter number of terms: “);
scanf(“%d”,&n);
for(i=0;i<n;i++)
{
scanf(“%d”,&a[i]);
}
avrg=avg(a,n);
printf(“\nThe average: %d”,avrg);
return 0;
}
int avg(int a[],int n)
{
int i,sum=0;
for(i=0;i<n;i++)
{
sum=sum+a[i];
}
return sum/n;
}
(b) What is a macro? Write the difference between macro and function.
Ans: A macro is a block or set of program code that is replaced by the value of the macro. It is a fragment of code that is given a name. A macro is defined by the preprocessor directive #define, which performs the action to replace the macro name with the macro value at the time of preprocessing. We can use macros whenever we want to repeatedly use a single value or a piece of code in our programs. By defining macros once in our program, we can use them frequently throughout the program.
Macros are pre-processed which means that all the macros would be processed before program compiles. Macro definitions need not be terminated by semi-colon (;). Macros can be used for a variety of purposes, such as creating constants, simplifying complex expressions, or generating repetitive code.
The program efficiency is increased by using Macros in c programs. Rather than mentioning a piece of code repeatedly in the programs, we can define the constant value once and use it frequently.
Difference between macro and functions:
Macro | Function |
Macros are pre-processed by the preprocessor | Functions are not pre-processed |
Macro is not compiled | Function is compiled |
Macros do not check for compilation error | Function checks for compilation error |
Macros are faster in execution than function | Functions are slower in execution than Macro |
A Macro is written at the beginning of a C Program | A Function is written as a statement block of a C Program |
In Macro, we can’t do recursion | In Function, we can do recursion |
Macros are useful when a small piece of code used in a program. | Functions are useful when a large piece of code used in a program. |
Generally, macros are of one line code | Function can be of any number of lines |
Before compilation process, the macro name is replaced by the macro value. | In a function call, transfer of control takes place. |
Macro increases the code length as it is added before the code while preprocessing. | Code length remains same. |
Macros cannot return values. | Functions can return values using the return statement. |
We cannot overload macros. | We can overload functions and provide different functionality for different sets of arguments. |
No Type Checking is done in Macro | Type Checking is Done in Function |
(c) Explain with example, how break and continue constructs are useful in C programming.
Ans: In C programming, the break and continue statements are control flow constructs that allow us to alter the flow of execution in loops (such as for, while, and do-while) and switch statements. These statements are particularly useful for improving the efficiency and readability of code.
break statement:
- The break statement is used to exit a loop prematurely. When encountered inside a loop, it immediately terminates the loop, and the program continues with the next statement after the loop.
- This can be useful when we want to exit a loop based on a certain condition, without waiting for the loop to complete all its iterations.
Example:
#include <stdio.h>
int main() {
int i;
for (i = 1; i <= 10; i++) {
if (i == 5) {
printf(“Breaking out of the loop at i = %d\n”, i);
break;
}
printf(“%d “, i);
}
return 0;
}
Output:
1 2 3 4 Breaking out of the loop at i = 5
continue statement:
- The continue statement is used to skip the rest of the code inside a loop for the current iteration and proceed with the next iteration of the loop.
- This can be helpful when we want to skip certain iterations based on a condition, without terminating the entire loop.
Example:
#include <stdio.h>
int main() {
int i;
for (i = 1; i <= 5; i++) {
if (i % 2 == 0) {
printf(“Skipping even number %d\n”, i);
continue;
}
printf(“%d “, i);
}
return 0;
}
Output:
1 Skipping even number 2
3 Skipping even number 4
5
In these examples, break is used to exit the loop when a certain condition is met, while continue is used to skip specific iterations of the loop based on a condition. These constructs enhance the flexibility and control over the flow of execution in C programs.