0% found this document useful (0 votes)
13 views16 pages

Unit 3 QB

Uploaded by

kuttysangeeth33
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views16 pages

Unit 3 QB

Uploaded by

kuttysangeeth33
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

UNIT -3

Question bank

1. List out the details you could infer from the following statement int sum(int, int);
The statement is function declaration statement. This declaration ensures that the compiler knows
the function's name, return type, and parameter list before its actual usage in the code.
The function returns a value of type int (integer). The function is named sum. The function takes
two parameters, both of which are of type int.

2. Find the output and justify


#include < stdio.h>
int sum two(int x, int y)
{ return x + y; }
void main()
{ printf(“%d”, sum tow(2,3)); }

The given code has several errors.

 Incorrect Header File Syntax:The header file < stdio.h> has a space after <
 Incorrect Function Name in Declaration and Definition: The function sum two is invalid, because
C does not allow spaces in function names
 Mismatch in Function Name During Call: In the printf statement, the function is called as sum
tow instead of sum two

3. “Could we able to create two different functions with same name in c” Justify
In C, it is not possible to create two different functions with the same name. This is because C does
not support function overloading, which allows multiple functions with the same name but different
parameters.

4. What will the following functions return


i) return pow(2,3)
ii) return round(3.5)
iii) return floor(3.9)
iv) return ceil(3.1)

i) return pow(2,3) – it returns 8.0


ii) return round(3.5) – it returns 4.0
iii) return floor(3.9) – it returns 3.0
iv) return ceil(3.1) – it returns 4.0

5. What are the different stages in defining a function in a complete code?


Function Declaration (Prototype): It specifies the function's name, return type, and parameter list
without including the actual implementation.
return_type function_name(parameter_list);

The compiler needs to be informed about the function because:

1. It ensures proper type checking for arguments and return values.


2. It allows memory allocation for the return type and parameters.
3. It enables the function to be called before its definition.
4. It facilitates the use of functions across multiple files.
5. It prevents undefined behavior and ensures program correctness.

Function Definition: Provides the actual implementation of the function. This is where the logic is
written.
return_type function_name(parameter_list) { // Function body (implementation) }

Function Call: Executes the function by passing the required arguments and using the returned value (if
any).

variable = function_name(arguments);

6.Explain with syntax on how to define a function


Syntax:
return_type function_name(parameter_list) {
// Function body
// Statements to perform the desired task
// Optional: return statement (if return_type is not void)
}
Description:

1. return_type:
o Specifies the type of value the function returns.
o Use void if the function does not return a value.
2. function_name:
o The name of the function, which is used to call it.
3. parameter_list:
o A list of input parameters the function accepts, including their data types.
o If the function takes no parameters, use void.
4. Function Body:
o Enclosed in { }, contains the code to execute the function's task.
o Use a return statement to return a value if the return type is not void.

7. Write a function to add one integer and one float number and returns the floor value in float.
#include <stdio.h>
#include <math.h>
float addAndFloor(int x, float y) {
float result = x + y;
return floor(result);
}
int main() {
int a = 5;
float b = 3.7;
printf("The floor of the sum is: %.2f\n", addAndFloor(a, b));
return 0;
}
8. List out different types of function calling parameters
Call by Value Function receives a copy of the argument's value. Used when don't need
Modifications do not affect the original value. to modify the
argument.
Call by Function receives the address of the argument, allowing it to Used When need to
Reference modify the original value. modify the argument.

9. “Function helps a lot in code reusability” Justify


 Instead of writing the same logic multiple times, define it in a function once and Whenever the
functionality is needed, call and reuse the same.
 It reduces redundancy and the chances of errors, as any changes to the logic need to be made only once
in the function definition.

10. Differentiate pass by value and pass by reference with respect to function calling
Feature Pass by Value Pass by Reference
Argument Passed A copy of the argument’s value. The address (reference) of the
argument.
Effect on Original No change to the original Modifies the original argument.
argument.
More memory usage due to Less memory usage, as only the
Memory Usage
copying the value. address is passed.
Can be slower with large data Faster for large data types (only
Performance
types (due to copying). address is passed).
When the function should not When the function should
Typical Use
modify the argument. modify the argument.

11. Compare and contrast looping and recursion function? Justify why recursion function required a base
condition to return.
Feature Looping Recursion

Definition Repetition of a block of code A function calling itself to solve


using constructs like for, while, a smaller instance of the same
or do-while. problem.

Control Mechanism Uses iterative constructs (e.g., Uses function calls and the
increment/decrement counters). program stack.

Termination Depends on a condition checked Depends on a base condition


during each iteration. specified within the recursive
function.

Performance Generally more efficient in Often uses more memory due to


terms of memory and execution repeated function calls (stack
time. frames).

Ease of Debugging Easier to debug as the flow is Harder to debug due to nested
linear and iterative. function calls.

Use Cases Suitable for problems with a Suitable for problems naturally
fixed or easily predictable defined in terms of smaller sub-
number of iterations. problems (e.g., factorial,
Fibonacci, tree traversals).

Stack Usage Does not use the program stack Explicitly uses the program
explicitly; uses looping stack for each function call.
variables.

Recursion with goto:


#include <stdio.h>
int fact(int N){
int r = 1;
loop:
if(N <= 1) return r;
r *= N--;
goto loop;
}
int main()
{
printf("%d",fact(5));
return 0;
}

Why Recursion Requires a Base Condition

1. Prevent Infinite Recursion:


o Without a base condition, the function keeps calling itself indefinitely, leading to a stack
overflow error due to the exhaustion of memory.
2. Define Stopping Point:
o A base condition defines the smallest or simplest instance of the problem for which the
solution is directly known. This stops further recursive calls and allows the function to
return a result.

12. What is the use of return statement explain with a small example of function definition.

The return statement is used in a function to:

1. Terminate the Function Execution:


o When the return statement is encountered, the function stops executing further code.
2. Return a Value to the Caller:
o The return statement can pass a value back to the point where the function was called,
enabling the caller to use that value.
3. Control the Flow of Execution:
o Functions can have multiple return statements to handle different conditions.

int square(int num) {

return num * num; // Returns the square of the input number

13. List out what you could infer from the following provided the address of x is say 1000

int x = 5;
int* p = &x;
Note: this is on 32 bit compiler

 x is stored at address 1000, taking up 4 bytes.


 The value of x is 5.
 p holds the address of x, which is 1000.
 Dereferencing p gives the value 5.
 Both int and pointers are 4 bytes each on a 32-bit compiler.

14. Explain referencing and dereferencing with an example


Referencing:
Referencing is the process of obtaining the memory address of a variable using the & (address-of)
operator.
int x = 10; int* p = &x; // Referencing: obtaining the address of 'x'
The &x operator retrieves the memory address of x, which is stored in the pointer p.

Dereferencing
Dereferencing is the process of accessing the value stored at the memory address that a pointer holds,
using the * (dereference) operator.

int x = 10;
int* p = &x; // Referencing
printf("Value of x: %d\n", *p); // Dereferencing: accessing the value at the address stored in 'p'

The *p operator accesses the value stored at that address, which is 10.

15. Draw and explain the memory diagram of double pointer?


A double pointer (also called a pointer-to-pointer) is a pointer that stores the address of another pointer.
int var = 10;
int *ptr1 = &a;
int **ptr2 = &ptr1; // Pointer to a pointer
printf("Value: %d\n", **ptr2); // Output: 10

16. Write a function definition to swap two variables with pass by reference method.
void swap(int* a, int* b) {
int temp = *a; // Store the value pointed to by 'a' in a temporary variable
*a = *b; // Assign the value pointed to by 'b' to the location pointed to by 'a'
*b = temp; // Assign the temporary value to the location pointed to by 'b'
}
17. Justify why and how wild pointer is not recommended and dangerous?
A wild pointer is a pointer in C that has not been initialized to a valid memory address. It contains a
garbage value (an arbitrary memory address) and does not point to any specific object or valid memory.

 Access to Unpredictable Memory:


 Wild pointers may point to an invalid or unallocated memory location, leading to unpredictable
behavior or crashes if dereferenced.

 Security Risks:

 Accessing random memory can lead to leakage of sensitive data or compromise program
integrity.

 Undefined Behavior:

 Dereferencing a wild pointer may result in undefined behavior, such as segmentation faults or
corruption of data in unintended memory regions.

18. If ptr is an integer pointer that points the address, say 1000, then find the following
i) ptr++
ii) ptr + 5
iii) ptr - 3
iv) if p is another pointer, points say 2000. Then p – ptr

i) ptr++ : Since an int is 4 bytes, ptr moves to 1000 + 4 = 1004

ii) ptr + 5 : ptr + 5 moves the pointer forward by 5 integer addresses 1000+5*4 = 1020
iii) ptr - 3 ptr - 3 moves the pointer backward by 3 integer addresses. 1000−(3×4)=1000−12=988
iv) if p is another pointer, points say 2000. Then p – ptr , (2000-1000)/4 = 250 elements

19. Differentiate near, far and huge pointer


Near pointer:
- Occupies 2 bytes.
- Cannot access memory outside the current segment (64 KB).
- Faster but limited in scope.
int near *np; // Near pointer is restricted to the current segment.
Far pointer
- Occupies 4 bytes.
- Can access memory across different segments.
- Requires switching between segments, which is slower.
int far *fp; // Far pointer can access data across segments.
Huge Pointer:
- Occupies 4 bytes.
- Can move freely between segments.
int huge *hp; // Huge pointer can normalize and access large data structures.
20. Differentiate constant pointer and pointer to a constant
Feature Constant Pointer (int* const p) Pointer to a Constant (const int* p
or int const* p)

Definition A pointer whose address cannot A pointer that cannot modify the
change after initialization. value it points to.

Address Cannot change the pointer to point to Can change the pointer to point to
Modifiability another address. another address.

Value Modifiability The value at the pointed address can The value at the pointed address
be modified. cannot be modified.

Declaration Syntax int* const p = &x; const int* p = &x; or int const* p =
&x;

21. Explain with an example how dangling pointer works.


A dangling pointer occurs when a pointer continues to reference a memory location after the memory it points
to has been deallocated or freed. In such cases, the pointer points to an invalid or unavailable memory
address, which can lead to undefined behavior, crashes, or data corruption if the pointer is dereferenced.
int *ptr = (int*) malloc(sizeof(int));
*ptr = 42;
free(ptr);
printf("After free (Dangling Pointer): %d\n", *ptr);

22. Declare the following


i) Null pointer
ii) Void pointer
iii) Integer pointer
iv) Structure pointer

i) int *null_ptr = NULL;


ii) void *void_ptr;
iii) int *int_ptr;
iv) struct Student {
int id;
char name[50];
};
// Structure pointer declaration
struct Student *struct_ptr;

23. What is output of the following

#include<stdio.h>
void main()
{
int arr[] = {11,21,13,41,15,61,17,81,19,20};
int* p;
p = arr;
printf(“%d\n%d\n%d\n%d\n”, *p, *p+3, *p+5, *p+8);
}

Output:
11
14
16
19
24. Justify how and why? “if pointer p points the base address of array arr, then arr[index] and *(p +
index) are same”*

p is a pointer to the base of the array, and p + index computes the address of the index-th element, which
is then dereferenced to retrieve its value.

Big questions

3. Discuss how pointer used in accessing array elements and array of pointers

Accessing Array Elements with Pointers

 Array Name as a Pointer:


The name of the array (e.g., arr) is a constant pointer to the first element (arr[0]). Thus, you can
use pointers to access array elements.
 Pointer Arithmetic:
By incrementing a pointer, you can move to the next element of the array, as pointers
automatically account for the size of the data type they point to.

Example: Accessing Array Elements with Pointers


#include <stdio.h>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr; // Pointer to the first element of the array
// Access elements using pointer arithmetic
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(p + i)); // Equivalent to arr[i]
}

return 0;
}
Output:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50

*(p + i) accesses the i-th element of the array, as p points to the base address of the array.

Array of Pointers

An array of pointers is a collection of pointers, where each pointer can point to a different memory
location. This is useful in scenarios like handling strings or dynamic memory allocation.

Example:

#include <stdio.h>

int main() {
const char *words[] = {"Hello", "World", "Pointers"}; // Array of string pointers

for (int i = 0; i < 3; i++) {


printf("Word[%d]: %s\n", i, words[i]); // Access each string
}
return 0;
}
Here, words is an array of pointers where each pointer points to the first character of a string literal.
7. Compare and contrast tail and non-tail recursion
Aspect Tail Recursion Non-Tail Recursion

Definition A recursive function is tail- A recursive function is non-tail-


recursive if the recursive call is recursive if further computation
the last operation performed is performed after the
before the function returns. recursive call returns.

Return Value Usage The return value of the recursive The return value of the recursive
call is directly returned. call is used in additional
computations before returning.

Optimization Can be optimized by the Cannot be optimized into a


compiler into a loop to save loop, leading to higher stack
stack space (tail-call usage.
optimization).

Memory Usage Requires less memory because Requires more memory because
only one stack frame is used at a each recursive call adds a new
time. stack frame until the base case is
reached.

Efficiency More efficient in terms of Less efficient due to higher


memory and stack usage. stack memory usage.

Example Use Cases Suitable for problems like Suitable for problems like tree
factorial, Fibonacci sequence, traversal and divide-and-
and simple traversal. conquer algorithms where
intermediate results need to be
combined.

int factorial_tail(int n, int result) int factorial_non_tail(int n) {


{ if (n == 0)
if (n == 0) return 1; // Base case
return result; // Base case return n * factorial_non_tail(n
return factorial_tail(n - 1, n * - 1); // Recursive call is followed
result); // Recursive call is the by multiplication
last operation }
}

10. Justify the following statement with an example. The statement is “Sometimes Recursion takes
more time and wastes recursive call for repeating the same recursive call ”

In some recursive implementations:


 The function repeatedly computes the result for the same input without storing or reusing
previously computed results.
 This leads to exponential growth in the number of recursive calls, increasing both time and
memory usage.

Example: Fibonacci Sequence (Naive Recursion)

Consider the Fibonacci sequence, where each term is the sum of the two preceding terms:

F(0) = 0,
F(1) = 1
F(n)=F(n−1)+F(n−2)
base cases are F(0)=0 and F(1)=1

#include <stdio.h>
int fibonacci(int n) {
if (n <= 1) // Base cases
return n;
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive calls
}

int main() {
int n = 5; // Find the 5th Fibonacci number
printf("Fibonacci(%d) = %d\n", n, fibonacci(n));
return 0;
}
Trace of Recursive Calls for fibonacci(5)
Redundant Calls:

 fibonacci(3) is calculated twice.


 fibonacci(2) is calculated three times.
 As n increases, the number of redundant calls grows exponentially.

Results in higher time complexity and inefficiency.

12. Discuss how to return an array and how to pass array as argument in a function with example.
write a program to that accepts 2 matrixes and checks whether 2 matrix can be multiplied or not,
if yes multiply them using functions.

Passing an Array as an Argument

When passing an array as an argument to a function, the base address of the array is passed, allowing the
function to operate on the original array.

#include<stdio.h>

int ArrayPrint( int b[],int s)

for(int i=0;i<s;i++)

printf("%d\n",b[i]); //b[i]=base address + i*4


}

int main()

int a[]={2,3,4,5,6};

int s=(sizeof(a)/sizeof(a[0]));

ArrayPrint(a,s);

In ArrayPrint(a,s), whole array is not passed. Only base address of the array is passed. So array name
which contains base address is always treated as pointer

#include <stdio.h>

// Function to check if matrix multiplication is possible


int canMultiply(int rowsA, int colsA, int rowsB, int colsB) {
return (colsA == rowsB);
}

// Function to multiply matrices


void multiplyMatrices(int matA[10][10], int matB[10][10], int result[10][10], int rowsA, int colsA, int
colsB) {
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
result[i][j] = 0;
for (int k = 0; k < colsA; k++) {
result[i][j] += matA[i][k] * matB[k][j];
}
}
}
}

// Function to display a matrix


void displayMatrix(int mat[10][10], int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
}

int main() {
int rowsA, colsA, rowsB, colsB;
int matA[10][10], matB[10][10], result[10][10];

// Input dimensions and elements of Matrix A


printf("Enter rows and columns for Matrix A: ");
scanf("%d %d", &rowsA, &colsA);
printf("Enter elements of Matrix A:\n");
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsA; j++) {
scanf("%d", &matA[i][j]);
}
}

// Input dimensions and elements of Matrix B


printf("Enter rows and columns for Matrix B: ");
scanf("%d %d", &rowsB, &colsB);
printf("Enter elements of Matrix B:\n");
for (int i = 0; i < rowsB; i++) {
for (int j = 0; j < colsB; j++) {
scanf("%d", &matB[i][j]);
}
}

// Check if matrices can be multiplied


if (canMultiply(rowsA, colsA, rowsB, colsB)) {
multiplyMatrices(matA, matB, result, rowsA, colsA, colsB);
printf("Resultant Matrix after Multiplication:\n");
displayMatrix(result, rowsA, colsB);
} else {
printf("Matrix multiplication not possible.\n");
}

return 0;
}

You might also like