Chapter - 8 Pointers in C, Computer Science, Class 10 / class ten, ASSEB ( SEBA), Prepared by Podmeswar through AI

Warning Disclaimer Notice:

The below answers and discussions are directly prepared by copy-paste from www.google.com, Googole AI Overview,  https://gemini.google.com/app , https://chatgpt.com/,etc,

These are only for understanding to improve the concept only; not for answers. We have not checked these clearly. Some mistakes may be happened. We are not responsible for any wrong information and answers. Please check yourself, yourselves and discuss with your expert teachers for the final approval or accepted the answers.  

Pointers in C

 

Example 8.1 A simple C program to display the address of a variable.

Example 8.1 shows a simple program to demonstrate the same. The program will

output a hexadecimal number that indicates the memory location where the variable x is stored.

Answer:

#include<stdio.h>

int main()

{

int x = 79;

printf( "\n Address of x in memory is %p", &x );

return 0;

}

 

Meaning and Output

This program demonstrates one of the most powerful concepts in C: Memory Addresses.

In C, every variable is stored at a specific location in the computer's RAM. The & (address-of) operator allows you to see exactly where that location is.

Breakdown of the Code

·         int x = 79;: This allocates a block of memory (usually 4 bytes for an integer) and stores the value 79 there.

·         &x: The ampersand is the Address-of Operator. It tells the program, "Don't give me the value 79; give me the memory location where 79 is stored."

·         %p: This is the format specifier specifically for pointers (memory addresses). It prints the address in Hexadecimal format (e.g., 00000078A1DFF734).


How to Interpret the Output

When you run this code, you will see an output similar to this:

Address of x in memory is 0x7ffcbd324e9c

1.      The 0x Prefix: This indicates that the number following it is in Hexadecimal (Base-16).

2.      Uniqueness: If you run this program on a different computer, or even run it again on the same computer, the address will likely change. This is because the Operating System assigns memory dynamically based on what is available at that moment.


Why is this useful?

Understanding memory addresses is the first step toward mastering Pointers. Pointers allow you to:

·         Pass large amounts of data to functions efficiently.

·         Manipulate memory directly for high-performance tasks.

·         Create dynamic data structures like Linked Lists and Trees.

A Quick Tip on Formatting

Your code is spread across many lines. While C is "whitespace-insensitive" (meaning it doesn't care about extra spaces or newlines), standard convention looks like this:

C

#include <stdio.h>

 

int main() {

    int x = 79;

    printf("\n Address of x in memory is %p", (void*)&x);

    return 0;

}

(Note: It is considered best practice to cast the address to (void*) when using %p to ensure compatibility across all systems.)

Would you like to see how you can use a Pointer variable to store this address and change the value of x indirectly?


 

Example 8.1 A simple C program to display the address of a variable.

Example 8.1 shows a simple program to demonstrate the same. The program will

output a hexadecimal number that indicates the memory location where the variable x is stored.

Answer:

#include<stdio.h>

int main()

{

int x = 79;

printf( "\n Address of x in memory is %p", &x );

return 0;

}

 

Quick activity: Run the above C program and analyze the output. What is the length of the hexadecimal number you get as an output?

 

Answer:

When you run this program on a modern computer, you are interacting with its architecture (the CPU and Operating System). Here is the analysis of the output and the answer to your question regarding the length of the hexadecimal number.

Analysis of the Output

When you run the program, the output will look something like this:

Address of x in memory is 0x7ffd56999a0c

·         0x: This is a prefix that tells you the number is in Hexadecimal (Base-16).

·         The Hexadecimal String: The letters and numbers (like 7ffd56999a0c) represent the exact physical location in the RAM where the integer 79 is stored.


The Length of the Hexadecimal Number

The length of the hexadecimal address depends on your system's architecture:

System Architecture

Pointer Size

Hexadecimal Length (approx.)

64-bit System (Standard today)

8 Bytes (64 bits)

12 to 16 digits

32-bit System (Older systems)

4 Bytes (32 bits)

8 digits

Why the variation in 64-bit systems?

Even though a 64-bit pointer can technically hold 16 hex digits ($16 \text{ digits} \times 4 \text{ bits/digit} = 64 \text{ bits}$), most modern processors (like x86-64) actually only use 48 bits for addressing. This is why you will frequently see 12 hexadecimal digits instead of the full 16. The computer often omits the "leading zeros" at the front of the address.


Key Takeaways

1.      Each Hex Digit = 4 Bits: This is why hexadecimal is used for memory; it maps perfectly to binary. Two hex digits represent exactly 1 byte (8 bits).

2.      Dynamic Addresses: If you close the program and run it again, the length of the number will stay the same, but the digits will change. This is due to ASLR (Address Space Layout Randomization), a security feature that moves programs around in memory to prevent hacking.

Would you like to see how to use the sizeof() operator to prove exactly how many bytes your system uses for a pointer?



 

Example 8.2 A simple C program to display the address of a variable and its size.

If we want to see the size of the address of x, we may use the sizeof() operator of C.

Example 8.2 shows this. The sizeof() operator returns the size in number of bytes.

Answer:

 

#include<stdio.h>

int main()

{

int x = 79;

printf( "\n Address of x in memory is %p", &x );

printf( "\n Size of the address of x is %u", sizeof(&x) );

return 0;

}

 

Meaning & Output:

This program builds on the previous one by not only showing you where the variable is in memory but also how much space the computer needs to store that memory address itself.

Analysis of the Output

When you run this code, you will see two lines of output. Here is a breakdown of what they mean:

1.      The Address (%p): This is the hexadecimal location of x.

o    Example Output: 0x7ffee1b28ac8

2.      The Size (%u): This is the size of the pointer (the address) in bytes.

o    Example Output (64-bit system): 8

o    Example Output (32-bit system): 4


Why is the size 8 (or 4)?

It is a common point of confusion: The size of the address is not the size of the variable.

·         The Variable (x): An int usually takes up 4 bytes. It stores the number 79.

·         The Address (&x): The address is like a "GPS coordinate." On a 64-bit operating system, every coordinate is 8 bytes (64 bits) long, regardless of whether it points to a tiny character or a massive array.

Entity

Purpose

Typical Size (64-bit)

x

Stores the integer value

4 Bytes

&x

Stores the memory location

8 Bytes


Technical Note: %u vs %zu

In your code, you used %u (unsigned int) to print the result of sizeof. While this works on many compilers, the technically correct format specifier for sizeof is %zu.

sizeof returns a type called size_t, which is specifically designed to handle the size of objects in memory. On some systems, using %u might trigger a compiler warning if the sizes don't match perfectly.

Observation on Memory Layout

When you see a very high hexadecimal address (like those starting with 0x7ff...), it usually indicates that your variable x is being stored on the Stack. The Stack is the area of memory where local variables inside functions (like main) are temporarily kept.

Would you like to see how to create a "Pointer Variable" that can store this address so you can modify x from a different function?


 

Example 8.2 A simple C program to display the address of a variable and its size.

If we want to see the size of the address of x, we may use the sizeof() operator of C.

Example 8.2 shows this. The sizeof() operator returns the size in number of bytes.

Answer:

 

#include<stdio.h>

int main()

{

int x = 79;

printf( "\n Address of x in memory is %p", &x );

printf( "\n Size of the address of x is %u", sizeof(&x) );

return 0;

}

 

 

 

Quick activity: Run the above C program and see the output. The computer you are using right now uses that many bytes for specifying the address of a variable.

Answer:

Since I am an AI running on a high-performance cloud environment, my "system" uses a 64-bit architecture.

When I simulate the execution of your code, here is the resulting output and analysis:

Simulated Output

Address of x in memory is 0x7ffd56999a0c

Size of the address of x is 8


Analysis of the Results

·         Size = 8 Bytes: The sizeof(&x) returns 8. This confirms that the environment uses 64-bit memory addressing ($8 \text{ bytes} \times 8 \text{ bits} = 64 \text{ bits}$).

·         The Address Length: You will notice the address 0x7ffd56999a0c contains 12 hexadecimal characters. Even though the pointer has the capacity for 16 characters (64 bits), the leading zeros are often omitted, or the system uses a 48-bit virtual address space, which is standard for modern x86-64 processors.

Why does this matter?

The fact that an address takes 8 bytes regardless of the data type it points to is fundamental to C programming. Whether you have an int, a char, or a massive struct, the "pointer" to that data will always be the same size (8 bytes on your system). This consistency is what allows arrays and complex data structures to function predictably.


A Note on the %u Warning

When running this, you might see a compiler warning like:

warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long unsigned int’

To make the code perfectly "portable" across all computers (32-bit and 64-bit), it is best to use %zu:

C

printf( "\n Size of the address of x is %zu", sizeof(&x) );

Would you like to see what happens to the size if we change x from an int to a char or a double?


 

Example 8.3 A simple C program to demonstrate a pointer variable.

 

Let us see a simple C program in Example 8.3 to understand the concept of pointer further.

In the program, ptr is declared as an integer type of pointer and it points to another integer

variable x.

Now, we can access x with the help of the pointer ptr. See the last printf() statement. We are displaying the value of x with *ptr. We have also displayed the address of x using ptr (second printf() statement).

 

Answer:

#include<stdio.h>

int main()

{

int x = 79;

int *ptr;

ptr = &x;

printf( "\n Address of x in memory is %p", &x );

printf( "\n Address of x in memory using pointer is %p", ptr );

printf( "\n Value of x is %d", x );

printf( "\n Value of x using pointer is %d", *ptr );

return 0;

}

 

Meaning & Output:

The provided C code demonstrates fundamental concepts of pointers, memory addresses, and variable values. The program successfully declares an integer variable x, a pointer to an integer ptr, assigns the address of x to ptr, and then prints the address and value of x in various ways. 

Here is the complete code with the corrected printf statement for proper formatting:

c

#include<stdio.h>

 

int main() {

    int x = 79;

    int *ptr;

    ptr = &x;

 

    printf("\nAddress of x in memory is %p", &x);

    printf("\nAddress of x in memory using pointer is %p", ptr);

    printf("\nValue of x is %d", x);

    printf("\nValue of x using pointer is %d", *ptr);

 

    return 0;

}

Explanation

·         #include<stdio.h>: This line includes the standard input/output library required for functions like printf.

·         int main() { ... }: This is the main function where the program execution begins.

·         int x = 79;: Declares an integer variable x and initializes its value to 79.

·         int *ptr;: Declares a pointer variable ptr that is specifically designed to store the memory address of an integer.

·         ptr = &x;: This is the key pointer operation. The address-of operator (&) gets the memory address of x, and this address is then stored in the pointer ptr.

·         printf("\nAddress of x in memory is %p", &x);:

o    Prints the memory address of x using the address-of operator (&x).

o    %p is the format specifier for printing a pointer (memory address).

·         printf("\nAddress of x in memory using pointer is %p", ptr);:

o    Prints the value stored in the ptr variable, which is the address of x.

o    As expected, the output of this line will be the same as the previous line.

·         printf("\nValue of x is %d", x);:

o    Prints the integer value stored in the variable x using the %d format specifier.

·         printf("\nValue of x using pointer is %d", *ptr);:

o    Prints the value at the address currently stored in ptr using the dereference operator (*).

o    The dereference operator "accesses the value pointed to" by the pointer. The output will be the integer 79. 

Output

The output of the program will look similar to this (the memory addresses will vary each time the program runs and across different computers): 

Address of x in memory is 0x7ffc7b7f1d4c

Address of x in memory using pointer is 0x7ffc7b7f1d4c

Value of x is 79

Value of x using pointer is 79

Example 8.4 A C program to demonstrate use of a pointer with a variable.

The pointer gives another way to reach the variable x. The variable x and *ptr can be used alternatively. Any operation done on x is the same doing on *ptr. For instance, if we want to add 7 with x, we may do so by x = x + 7 or, *ptr = *ptr +7, in either way. The programs in Example 8.4 and 8.5 will give the same output. Both will increment the value of the variable by 7.

Answer:

#include<stdio.h>

int main()

{

int x = 79;

int *ptr;

ptr = &x;

x = x + 7;

printf("\n Value of x is %d", x);

printf("\n Value of x using pointer is %d", *ptr);

return 0;

}

 

 

Meaning & Output:

The provided C code will compile and run, producing the following output:

 Value of x is 86

 Value of x using pointer is 86

Explanation

1.    Initialization: An integer variable x is initialized with the value 79, and a pointer ptr is declared.

2.    Pointer Assignment: The pointer ptr is assigned the memory address of x (ptr = &x). Now, ptr "points to" x.

3.    Variable Modification: The value of x is updated to x + 7, making x equal to 86.

4.    Printing:

1.    printf( \n Value of x is %d , x); prints the current value stored in the variable x, which is 86.

2.    printf( \n Value of x using pointer is %d , *ptr); uses the dereference operator (*) on the pointer ptr. Dereferencing a pointer accesses the data at the memory address it points to. Since ptr points to x, it retrieves the value of x, which is also 86


 

Example 8.5 A C program to demonstrate simple operations using a pointer.

Answer:

#include<stdio.h>

int main()

{

int x = 79;

int *ptr;

ptr = &x;

*ptr = *ptr + 7;

printf("\n Value of x is %d", x);

printf("\n Value of x using pointer is %d", *ptr);

return 0;

}

 

Meaning & Output:

The provided C code demonstrates basic pointer usage, specifically how a pointer can modify the value of the variable it points to. 

Here is the code with the expected output:

c

#include<stdio.h>

 

int main() {

    int x = 79;

    int *ptr;

    ptr = &x;

    *ptr = *ptr + 7;

    printf("\n Value of x is %d", x);

    printf("\n Value of x using pointer is %d", *ptr);

    return 0;

}

Explanation of the Code and Output

1.    int x = 79;: An integer variable x is declared and initialized with the value 79.

2.    int *ptr;: A pointer variable ptr is declared, capable of storing the memory address of an integer.

3.    ptr = &x;: The address of variable x (using the address-of operator &) is assigned to the pointer ptrptr now "points to" x.

4.    *ptr = *ptr + 7;:

1.    The dereference operator * accesses the value stored at the address ptr points to (which is the value of x, currently 79).

2.    The expression evaluates to 79 + 7, resulting in 86.

3.    This new value (86) is then assigned back to the memory location pointed to by ptr (which is x itself). The value of x is now updated to 86.

                printf(...): The printf statements print the value of x directly, and then the value of x indirectly through the pointer *ptr

Output:

 Value of x is 86

 Value of x using pointer is 86


 

 

Example 8.6 A C program where a pointer points to different variables at different times.

Example 8.6 shows a C program where the pointer was initially pointing to x and then it points to the variable y. Both x and y are int type variables. The first printf() displays 79 and the second printf() displays 27.

Answer:

 

#include<stdio.h>

int main()

{

int x = 79, y = 27;

int *ptr;

ptr = &x;

printf("\n Value of x using pointer is %d", *ptr);

ptr = &y;

printf("\n Value of y using pointer is %d", *ptr);

return 0;

}

 

Meaning & Output:

The provided C code demonstrates the basic usage of pointers. The program declares two integer variables, x and y, and an integer pointer ptr

Code Explanation:

·         int x = 79, y = 27;: Declares and initializes two integer variables.

·         int *ptr;: Declares a pointer variable ptr that can hold the address of an integer.

·         ptr = &x;: Assigns the memory address of x to ptr.

·         printf("Value of x using pointer is %d", *ptr);: Prints the value at the address currently stored in ptr, which is the value of x (79). The * operator dereferences the pointer.

·         ptr = &y;: Reassigns the memory address of y to ptr.

·         printf("Value of y using pointer is %d", *ptr);: Prints the value at the new address stored in ptr, which is the value of y (27). 

Output of the Program:

When compiled and run, the program will produce the following output:

Value of x using pointer is 79

Value of y using pointer is 27


 

Example 8.7 A C program using a pointer for a char type variable.

In all the examples above, a pointer was used to point to an integer. It can also be used to point to other types of variables. In Example 8.7, we present a C program to access a character variable using a pointer. The syntax remains the same.

Answer:

#include<stdio.h>

int main()

{

char x = 'A';

char *ptr;

ptr = &x;

printf("\n Value of x using pointer is %c", *ptr);

return 0;

}

 

Meaning & Output:

The provided C code is a complete and correct program that demonstrates the basic use of a pointer to access the value of a character variable. 

Code Description

·         #include<stdio.h>: Includes the standard input/output library needed for the printf function.

·         int main(): The main function where program execution begins.

·         char x = 'A';: Declares a character variable x and initializes it with the value 'A'.

·         char *ptr;: Declares a pointer variable ptr that is designed to store the memory address of a char type variable.

·         ptr = &x;: Assigns the address of the variable x to the pointer ptr using the address-of operator (&).

·         printf(...): Prints the value stored at the memory location pointed to by ptr using the dereference operator (*).

·         return 0;: Indicates that the program executed successfully. 

Output

When compiled and run, the program produces the following output:

 Value of x using pointer is A


 

Example 8.8 A C program where pointers are used for different types of variables.

Now, let us see an interesting behaviour of pointers. Have a look at the C program presented in Example 8.8. We have used two pointers *chPtr and *intPtr. The first pointer points to a char type variable and the second pointer points to an int type variable.

Answer:

#include<stdio.h>

int main()

{

char x = 'A';

char *chPtr;

chPtr = &x;

printf("\n Value of x using pointer is %c", *chPtr);

printf("\n Value of the pointer is %p", chPtr);

chPtr++;

printf("\n Value of the pointer after increment is %p", chPtr);

/* Using pointer for int */

int y = 27;

int *intPtr;

intPtr = &y;

printf("\n\n Value of y using pointer is %d", *intPtr);

printf("\n Value of the pointer is %p", intPtr);

intPtr++;

printf("\n Value of the pointer after increment is %p", intPtr);

printf("\n\n");

return 0;

}

 

 

Meaning & Output:

 

The provided C code demonstrates pointer arithmetic with char and int data types. When a pointer is incremented, it moves to point to the next memory location of the size of the data type it points to, rather than just the next byte [1]. 

The expected output illustrates this behavior:

 Value of x using pointer is A

 Value of the pointer is 0x7ffd...a0 (example address)

 Value of the pointer after increment is 0x7ffd...a1 (example address, moves by 1 byte)

 

 Value of y using pointer is 27

 Value of the pointer is 0x7ffd...b0 (example address)

 Value of the pointer after increment is 0x7ffd...b4 (example address, moves by 4 bytes on typical systems)

Key Concepts

·         char pointers: A char is typically 1 byte in size. Incrementing a char* adds 1 to the memory address.

·         int pointers: An int is typically 4 bytes (or 2 or 8, depending on the system/compiler) in size. Incrementing an int* adds the size of an int to the memory address, e.g., 4 bytes on most modern 32/64-bit systems [1]. The compiler automatically handles the byte arithmetic based on the pointer's data type.

·         Memory Addresses: The exact hexadecimal values of the memory addresses (0x...) will vary each time the program runs, as the operating system allocates different memory locations for variables.

·         %p format specifier: This is used to print the value of a pointer (a memory address) in hexadecimal format [1]. 

The code you provided correctly implements these concepts to show how pointer arithmetic works in C.


 

Example 8.8 A C program where pointers are used for different types of variables.

Now, let us see an interesting behaviour of pointers. Have a look at the C program presented in Example 8.8. We have used two pointers *chPtr and *intPtr. The first pointer points to a char type variable and the second pointer points to an int type variable.

Answer:

#include<stdio.h>

int main()

{

char x = 'A';

char *chPtr;

chPtr = &x;

printf("\n Value of x using pointer is %c", *chPtr);

printf("\n Value of the pointer is %p", chPtr);

chPtr++;

printf("\n Value of the pointer after increment is %p", chPtr);

/* Using pointer for int */

int y = 27;

int *intPtr;

intPtr = &y;

printf("\n\n Value of y using pointer is %d", *intPtr);

printf("\n Value of the pointer is %p", intPtr);

intPtr++;

printf("\n Value of the pointer after increment is %p", intPtr);

printf("\n\n");

return 0;

}

 

 

Quick activity: Run the above C program and observe the output of the program carefully.

Answer:

 

Since I am an AI, I will simulate the execution of your code on a standard 64-bit Linux environment (which is common for modern C compilers like GCC).

The output below reflects exactly what happens in the computer's memory during pointer arithmetic.

Simulated Output

Plaintext

 Value of x using pointer is A
 Value of the pointer is 0x7ffd5a10f637
 Value of the pointer after increment is 0x7ffd5a10f638
 
 Value of y using pointer is 27
 Value of the pointer is 0x7ffd5a10f63c
 Value of the pointer after increment is 0x7ffd5a10f640

Careful Observation & Analysis

If you look closely at the addresses, you will see the "magic" of how C handles memory based on data types.

1. The char Pointer (1-Byte Jump)

·         Before: ...f637

·         After: ...f638

·         Difference: 1 byte.

·         Why? A char is exactly 1 byte. When you say chPtr++, the compiler moves the pointer to the very next byte in memory.

2. The int Pointer (4-Byte Jump)

·         Before: ...f63c

·         After: ...f640

·         Difference: 4 bytes.

·         Why? In hexadecimal, c is 12. Adding 4 brings you to 16, which in hex resets the digit to 0 and carries 1 to the next place. Since an int is 4 bytes, the compiler moves the pointer 4 bytes forward to reach where the next integer would theoretically start.


Important Technical Concepts

·         Scaling: Pointer arithmetic is scaled by the size of the data type. The formula the CPU uses is:

$$\text{New Address} = \text{Current Address} + (\text{Step} \times \text{sizeof(type)})$$

·         Hexadecimal Counting: Remember that hex goes 0, 1, 2... 8, 9, a, b, c, d, e, f. This is why jumping 4 bytes from an address ending in c results in an address ending in 0.

·         Dangling Pointers: After you run intPtr++, the pointer is now looking at a memory location that doesn't belong to the variable y. If you tried to print *intPtr now, you would get a "garbage value" (random data left over in RAM).

Would you like me to show you how this same logic allows you to navigate through an Array without using square brackets []?


 

Example 8.9 A C program displaying the addresses of the array elements.

Let us first see how we can access the elements of an array using pointers. We have already

seen that when we declare an array, a certain amount of memory is allocated by the compiler.

For example, an int array of size 5 will allocate 20 bytes (assuming int takes 4 bytes, 5x4=20).

Have a look at the simple C program in Example 8.9. We have taken an int array of size 5

and we have initialized some values to the elements. We have then displayed the addresses of

these array elements.

 

Answer:

#include<stdio.h>

int main()

{

int x[5] = {7, 8, 1, 0, 1};

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

{

printf( "\n Address of element %d is %p", i, &x[i] );

}

printf( "\n\n Base Address of the array is %p", x );

return 0;

}

 

MEANING & OUTPUT:

 

This C program declares an integer array x of size 5 with values {7,8,1,0,1}. It iterates through the array, printing the memory address of each element (&x[i]) using the %p format specifier, and finally prints the base address of the array (the address of the first element). 

 

Expected Output Structure (Addresses will vary): 

text

Address of element 0 is 0x7ffd...a0

Address of element 1 is 0x7ffd...a4

Address of element 2 is 0x7ffd...a8

Address of element 3 is 0x7ffd...ac

Address of element 4 is 0x7ffd...b0

 

Base Address of the array is 0x7ffd...a0

Key Points: 

  • %p: Used to print pointer values (addresses) in hexadecimal format.
  • &x[i]: Takes the address of the 𝑖-th element.
  • x: Represents the base address of the array, equivalent to &x[0].

Memory layout: Each integer element typically takes 4 bytes, so addresses increase by 4 (e.g., a0, a4, a8, ac, b0). 
Example 8.10 A C program displaying the addresses of the array elements.

If we need to access all the elements one-by-one, we can use a loop as follows.

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

{

printf( "\n Value of element %d is %d", i, *(x+i) );

}

The program where the elements of an array are accessed using pointer is shown in

Example 8.10. The output of the same is shown using Figure 8.4.

#include<stdio.h>

int main()

{

int x[5] = {7, 8, 1, 0, 1};

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

{

printf( "\n Value of element %d is %d", i, *(x+i) );

}

return 0;

}

 

Meaning & Output:

The program outputs the following lines to the console:

Value of element 0 is 7
Value of element 1 is 8
Value of element 2 is 1
Value of element 3 is 0
Value of element 4 is 1 

 

Explanation 

The C code initializes an integer array x with values {7, 8, 1, 0, 1}. A for loop iterates five times, with the loop variable i ranging from 0 to 4. In each iteration, the printf function prints the current value of i and the value of the array element at index i, which is accessed using pointer arithmetic *(x+i) (equivalent to x[i]). Each printed line is preceded by a newline character. 


 

Example 8.11 A C program showing dynamic memory allocation.

Answer:

#include<stdio.h>

#include <stdlib.h>

int main()

{

int *age, personCount;

printf("\n How many persons are there? ");

scanf("%d", &personCount);

age = (int*) malloc ( personCount * sizeof(int) );

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

{

printf( "\n Enter age of person %d ", i );

scanf("%d", *(age + i) );

}

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

{

printf( "\n Age of person %d is %d", i, *(age + i) );

}

return 0;

}

 

Meaning & Output:

All the programs we have seen so far were using only the stdio.h header file. But the program in Example 8.11 uses another header file stdlib.h. This header file provides support for the malloc() library function. In case the system fails to allocate the requested amount of memory in the malloc() function, it returns NULL.

 

 

It looks like you are working on a C program to dynamically allocate memory for an array of integers. You have the logic mostly correct, but there is a small but critical error in your first scanf inside the for loop that will cause the program to crash (a segmentation fault).

The Bug

In your first loop, you wrote:

scanf("%d", *(age + i) );

Why this is a problem:

The scanf function requires a memory address (a pointer) to know where to store the input. By using the dereference operator *, you are passing the value stored at that memory location instead of the address. Since the memory is newly allocated, it contains junk data, and scanf tries to treat that junk data as a memory address, leading to a crash.


The Fix

You have two ways to write this correctly:

1.        Using Pointer Arithmetic: Pass (age + i) without the *.

2.        Using Array Notation: Pass &age[i]. This is often more readable.

 

 

Corrected Code

C

#include <stdio.h>

#include <stdlib.h>

 

int main() {

    int *age, personCount;

 

    printf("\n How many persons are there? ");

    scanf("%d", &personCount);

 

    // Allocate memory

    age = (int*) malloc(personCount * sizeof(int));

 

    // Check if memory allocation was successful

    if (age == NULL) {

        printf("Memory allocation failed!");

        return 1;

    }

 

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

        printf("Enter age of person %d: ", i + 1);

        // FIX: Pass the address (age + i) OR &age[i]

        scanf("%d", (age + i));

    }

 

    printf("\n--- Results ---");

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

        printf("\n Age of person %d is %d", i + 1, *(age + i));

    }

 

    // Best practice: Free the memory before exiting

    free(age);

 

    return 0;

}

 

Key Improvements

·         Added free(age): Whenever you use malloc, you should use free to prevent memory leaks.

·         NULL Check: It’s good practice to check if malloc returned NULL, which happens if the system runs out of memory.

·         Cleaned up i + 1: In the printf, I used i + 1 so the user sees "Person 1" instead of "Person 0", which is more natural for non-programmers.

 

OUTPUT:

The output of the C program depends on the user input for the number of persons and their respective ages. Assuming the user inputs 3 for the number of persons, and then 2530, and 22 for their ages, the program would display the following output: 

 

 How many persons are there? 3

 Enter age of person 1: 25

 Enter age of person 2: 30

 Enter age of person 3: 22

 

--- Results ---

 Age of person 1 is 25

 Age of person 2 is 30

 Age of person 3 is 22

 

The program first prompts the user for the number of people. It then allocates memory dynamically using malloc to store their ages. A loop is used to collect each person's age from the user. Finally, the program prints the entered ages in a formatted list. The free(age); line ensures the allocated memory is returned to the system before the program exits. 


 

Example 8.12 Another C program showing dynamic memory allocation.

All the programs we have seen so far were using only the stdio.h header file. But the program in Example 8.11 uses another header file stdlib.h. This header file provides support for the malloc() library function. In case the system fails to allocate the requested amount of memory in the malloc() function, it returns NULL. We may also check this using a conditional statement. If the malloc() function returns NULL, we may terminate the program. Otherwise we may proceed normally. Example 8.12 shows this.

Answer:

#include<stdio.h>

#include <stdlib.h>

int main()

{

int *age, personCount;

printf("\n How many persons are there? ");

scanf("%d", &personCount);

age = (int*) malloc ( personCount * sizeof(int) );

if( age = = NULL )

{

printf(" \n Sorry! Requested memory cannot be allocated.");

return 0;

}

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

{

printf( "\n Enter age of person %d ", i );

scanf("%d", (age + i) );

}

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

{

printf( "\n Age of person %d is %d", i, *(age + i) );

}

return 0;

}

 

Meaning & Output:

This C code is a standard example of dynamic memory allocation using malloc(). It successfully asks the user for a number of people, allocates enough memory to store their ages, then collects and prints those ages. 

Here is a breakdown of the program's logic and a slightly cleaned-up version for better readability:

 

Code Explanation

1.     Include Headers:

·         stdio.h: Provides standard input/output functions like printf() and scanf().

·         stdlib.h: Provides functions for memory allocation and other utilities, specifically malloc().

 

                main Function: The entry point of the program.

 

                Variable Declarations:

·         int *age: A pointer to an integer. This pointer will hold the address of the first byte of the dynamically allocated memory block.

·         int personCount: An integer to store how many ages the user wants to enter.

 

                Get Input:

·         The program prompts the user for the number of people.

·         scanf() reads that number into personCount.

 

                Dynamic Memory Allocation:

·         age = (int*) malloc(personCount * sizeof(int));

·         malloc() attempts to reserve a block of memory large enough to hold personCount integers.

·         The result (the starting address of the block) is cast to an int* and assigned to the age pointer.

 

                Error Handling:

·         if( age == NULL ): Checks if malloc() failed to allocate memory (e.g., if the requested amount was too large). If it fails, it prints an error message and exits the program.

 

                Input Loop (Collecting Ages):

·         for loop iterates personCount times.

·         Inside the loop, it prompts for the age of each person and uses scanf() to store the input directly into the allocated memory block using pointer arithmetic (age + i).

 

                Output Loop (Displaying Ages):

·         Another for loop iterates personCount times.

·         It prints the stored age for each person using pointer dereference *(age + i).

 

                Return 0: Indicates successful program execution. 


Cleaned Up Code

The original code works, but adding newlines correctly and using better formatting makes it clearer. In a real-world application, it is also best practice to use free(age) before the program terminates to return the allocated memory to the system, though modern operating systems clean this up automatically when the process ends. 

 

#include <stdio.h>

#include <stdlib.h>

 

int main() {

    int *age, personCount;

 

    // Fixed printf formatting for proper newlines

    printf("\nHow many persons are there? ");

   

    // Check if scanf successfully read input (optional, but good practice)

    if (scanf("%d", &personCount) != 1 || personCount <= 0) {

        printf("\nInvalid input for person count.\n");

        return 1; // Exit with error code

    }

 

    // Allocate memory

    age = (int*) malloc(personCount * sizeof(int));

   

    // Error handling

    if (age == NULL) {

        printf("\nSorry! Requested memory cannot be allocated.\n");

        return 1; // Exit with error code

    }

 

    // Collect input

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

        printf("\nEnter age of person %d: ", i + 1); // Displaying 1-based index for user

        scanf("%d", (age + i));

    }

 

    // Display output

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

        printf("\nAge of person %d is %d", i + 1, *(age + i));

    }

 

    // Best practice: free the allocated memory

    free(age);

    age = NULL; // Prevent using dangling pointer

 

    printf("\n\nProgram finished successfully.\n");

    return 0;

}

Exercise

1. How is a pointer variable different from a normal variable? (in C Program)

Answer:

In the C programming language, a normal variable stores a specific value (like an integer or a character), whereas a pointer variable stores the memory address of another variable [1]. [1, 2, 3]

 

Key differences include:

Feature [4, 5, 6, 7, 8]

Normal Variable

Pointer Variable

Purpose

Stores data (e.g., int x = 10;) [1].

Stores a memory address (e.g., the location of x).

Value

The actual data value (10) [1].

A memory address (e.g., 0x7ffee...) [1].

Declaration

int a; or char c;

int *ptr; or char *p; (using the asterisk *) [1].

Size

Varies by data type (e.g., int is typically 4 bytes).

A fixed size for memory addresses, typically 8 bytes on 64-bit systems, regardless of the type it points to [1].

Access

Accessed directly by its name [1].

Accessed using dereferencing (*ptr) to get the value at the address it holds [1].

 

Essentially, a normal variable is like a storage box for data, while a pointer variable is like a note with directions on how to find another specific storage box. Pointers are crucial for tasks like dynamic memory allocation, working with arrays efficiently, and building complex data structures like linked lists [1]. [9, 10, 11, 12, 13]


 

2. Why is dynamic memory allocation an efficient memory management technique?

Answer:

Dynamic memory allocation is an efficient memory management technique in C programming primarily because it provides the flexibility to manage memory at runtime, leading to optimized memory usage, improved program performance, and greater control over memory resources. 

 

Key reasons for its efficiency include:

 

·         Optimal Memory Utilization: Static and automatic memory allocation techniques often require specifying the size of data structures during compilation. This can lead to reserving more memory than needed (wasting space) or not enough (causing errors). Dynamic allocation allows the program to request exactly the amount of memory required during execution, preventing wastage and ensuring resources are used efficiently.

·         Handling Variable Sized Data: Programs often deal with data whose size is unknown at compile time (e.g., user input, data read from a file, linked lists). Dynamic memory allocation (using functions like malloc()calloc()realloc(), and free()) allows for the creation of data structures that can grow or shrink as needed at runtime, adapting to the actual data requirements.

·         Increased Program Flexibility: Dynamic memory enables the creation of complex data structures like linked lists, trees, and graphs, which cannot be efficiently implemented using static allocation due to their variable and dynamic nature. This flexibility is crucial for building robust and scalable applications.

·         Memory Longevity Control: Variables allocated dynamically in the heap remain allocated until they are explicitly deallocated using the free() function or the program terminates. This allows data to persist even after the function that created it has finished executing, which is essential for managing persistent data across different parts of a program.

·         Reduced Stack Overflow Risk: Allocating large blocks of data on the stack (automatic allocation) can lead to a stack overflow. Dynamic memory uses the heap, which is typically much larger than the stack, providing ample space for large data requirements and preventing stack-related crashes. 


 

3. How many bytes are needed to store an int pointer variable? Is it the same for a char pointer variable? Write a simple C program to explain your answer.

Answer:

 


The number of bytes needed to store a pointer variable depends on the architecture of the computer system (e.g., 32-bit or 64-bit), not the type of data it points to. A pointer holds a memory address, and the size of that address is fixed for a given system [1, 2]. 

·         On a 32-bit system, a pointer is typically 4 bytes.

·         On a 64-bit system, a pointer is typically 8 bytes. 

Therefore, the size of an int pointer and a char pointer is the same on a specific system because both are storing a memory address. 

C Program Explanation

The following C program uses the sizeof operator to demonstrate the size of an int pointer and a char pointer on the system where it is compiled. 

c

#include <stdio.h>

 

int main() {

    int* int_ptr;

    char* char_ptr;

    int int_size = sizeof(int_ptr);

    int char_size = sizeof(char_ptr);

 

    printf("Size of int pointer (int*): %d bytes\n", int_size);

    printf("Size of char pointer (char*): %d bytes\n", char_size);

 

    if (int_size == char_size) {

        printf("\nYes, the sizes are the same. A pointer's size depends on the system architecture (e.g., 32-bit or 64-bit) for storing the memory address, not the type of data it points to.\n");

    } else {

        printf("\nNo, the sizes are different. This result is unexpected under normal circumstances.\n");

    }

 

    return 0;

}

</code>

 

**Example Output (on a 64-bit system):**

 

Size of int pointer (int*): 8 bytes
Size of char pointer (char*): 8 bytes 

Yes, the sizes are the same. A pointer's size depends on the system architecture (e.g., 32-bit or 64-bit) for storing the memory address, not the type of data it points to. 

{content: }


 

4. Write the output of the following code segment. (a)

 

int *ptr, x = 9;

ptr = &x;

printf("\n %d", (*ptr)++);

Answer:

The output of the code segment is 9

text

 9

Explanation:

1.    int *ptr, x = 9;: An integer x is initialized to 9, and ptr is declared as a pointer to an integer.

2.    ptr = &x;ptr now stores the memory address of x.

3.    (*ptr)++: The post-increment operator (++) increments the value of x after the current expression is evaluated. The expression (*ptr) dereferences the pointer to access 9, which is printed. Afterward, the value of x becomes 10.

4.    The \n in printf causes a newline to be printed before the number 9. 


 

4. Write the output of the following code segment. (b)

int *ptr, x = 9;

ptr = &x;

printf("\n %d", (*ptr)++);

printf("\n %d", *ptr);

Answer:

The output of the code segment is:

 9

 10

Explanation:

1.    int *ptr, x = 9;: Declares an integer variable x initialized to 9, and an integer pointer ptr.

2.    ptr = &x;: Assigns the memory address of x to ptrptr now points to x.

3.    printf("\n %d", (*ptr)++);:

1.    *ptr accesses the value at the address pointed to by ptr (which is 9).

2.    The post-increment operator (++) is applied to the value being pointed to. In post-increment, the current value is used first, and then it is incremented.

3.    The value 9 is printed.

4.    After the print statement executes, the value in memory pointed to by ptr (which is x) is incremented to 10.

                printf("\n %d", *ptr);:

0.    *ptr accesses the value currently stored at the address pointed to by ptr (which is now 10).

1.    The value 10 is printed


 

4. Write the output of the following code segment. (c)

int *ptr, x = 9;

ptr = &x;

int y = ++(*ptr);

printf("\n %d", y);

Answer:

The output of the code segment is:

 10

Here is a breakdown of the code execution:

·         int *ptr, x = 9;: An integer variable x is declared and initialized to 9, and an integer pointer ptr is declared.

·         ptr = &x;: The pointer ptr is assigned the memory address of x.

·         int y = ++(*ptr);:

o    *ptr dereferences the pointer, accessing the value stored at x's memory location (which is 9).

o    ++(*ptr) uses the pre-increment operator, which increases the value of x to 10 before it is used in the assignment.

o    The new value of x, which is 10, is then assigned to the new integer variable y.

·         printf("\n %d", y);: The value stored in y (which is 10) is printed to the console. 


 

4. Write the output of the following code segment. (d)

char *ptr, x = 'A';

ptr = &x;

char y = *ptr;

printf("\n %c", y);

Answer:

The output of the code segment is:

 A

The code declares a char variable x with the value 'A' and a char pointer ptr. It then assigns the address of x to ptr. A new char variable y is declared and assigned the value pointed to by ptr (which is the value of x). Finally, the program prints the character stored in y using printf


 

4. Write the output of the following code segment. (e)

 

char *ptr, x = 'A';

ptr = &x;

char y = (*ptr)++;

printf("\n %c", y);

Answer:

The variable y is assigned the value of *ptr (which is 'A') after *ptr is incremented. The post-increment operator (++ after *ptr) means the original value of *ptr ('A') is used in the assignment expression for y before the increment takes effect. The variable x and the value *ptr are both incremented to 'B', but the variable y retains the original 'A'. 

Wait, my explanation of post-increment was incorrect for C. Let me rethink the assignment char y = (*ptr)++;

In C, the post-increment operator means the value is used in the expression before the increment happens. 

1.    x is 'A'.

2.    ptr points to x.

3.    *ptr evaluates to 'A'.

4.    'A' is assigned to y. So y becomes 'A'.

5.    *ptr is incremented to 'B'. So x becomes 'B'.

6.    printf("\n %c", y); prints y

So the output should be A, not B. Let me double check the user request.

"Write the output of the following code segment."

The code:

c

char *ptr, x = 'A';

ptr = &x;

char y = (*ptr)++;

printf("\n %c", y);

Yes, my second thought is correct. The post-increment operator results in the original value being used in the expression. 

 

The output of the code segment is:

 A

Why is the output 'A' and not 'B'?

The result depends on the Post-Increment Operator (++ placed after the variable). Here is the step-by-step breakdown:

1.      ptr = &x;: The pointer ptr now holds the memory address of the character variable x (which is 'A').

2.      (*ptr)++: This instruction tells the computer to increment the value located at the address ptr. However, because it is a post-increment, the current value is used in the expression before the increment happens.

3.      The Assignment:

o    The value of *ptr (which is 'A') is first assigned to y.

o    After the assignment is complete, the value of x is incremented to 'B'.

4.      The Print: printf displays the value of y, which was captured as 'A'.


Comparison Table

If you had changed the placement of the increment operator, the results would differ:

Code Segment

Value of y

Value of x

y = (*ptr)++; (Post-increment)

'A'

'B'

y = ++(*ptr); (Pre-increment)

'B'

'B'

Would you like to see how this behavior changes if we use parentheses differently, such as *ptr++?


 

4. Write the output of the following code segment.

(f)

char *ptr, x = 'A';

ptr = &x;

char y = ++(*ptr);

printf("\n %c", y);

Answer:

The output of the code segment is:

 B

The variable x is initialized to the character 'A'. The pointer ptr is then assigned the address of x. The expression ++(*ptr) pre-increments the value pointed to by ptr, which is the value of x. The character 'A' is incremented to 'B'. This new value is then assigned to the character variable y, which is subsequently printed.

 

Explanation

In this version of the code, you are using the Pre-increment Operator (++ placed before the variable). Here is how the computer processes the line char y = ++(*ptr);:

1.      Dereference: The computer looks at *ptr, which points to the value of x (initially 'A').

2.      Increment First: Because the ++ is before the variable, the value stored at that memory address is incremented before it is used for anything else. In the ASCII table, the character after 'A' is 'B'.

3.      Assignment: The newly incremented value ('B') is then assigned to the variable y.

4.      Final Result: When printf runs, y holds the value 'B'.


Key Difference from your previous example

It all comes down to the "Pre" vs "Post" timing:

·         (*ptr)++ (Post-increment): Use the value first, then increment. (Result was A)

·         ++(*ptr) (Pre-increment): Increment first, then use the value. (Result is B)

A Warning on Parentheses

The parentheses (*ptr) are very important here. If you wrote ++*ptr, it would still work the same way because of operator precedence. However, if you wrote *ptr++ (without parentheses), the computer would increment the address the pointer points to rather than the value inside it.

Would you like to see an example of how the pointer address itself can be incremented?

 


 

4. Write the output of the following code segment.

(g)

char *ptr, x = 'A';

ptr = &x;

char *y;

y = ptr;

printf( "\n %c", ++(*y) );

Answer:

The output of the code segment is:

 B

 

Explanation:

1.    char *ptr, x = 'A';: A character variable x is initialized with the value 'A', and a character pointer ptr is declared.

2.    ptr = &x;: The address of x is assigned to ptr.

3.    char *y;: A character pointer y is declared.

4.    y = ptr;: The value of ptr (which is the address of x) is assigned to y. Both pointers now point to the same memory location where 'A' is stored.

5.    printf( "\n %c", ++(*y) );:

1.    *y dereferences the pointer y, accessing the value at its memory location, which is currently 'A'.

2.    The pre-increment operator ++ increments this value. Since 'A' is an ASCII value, incrementing it changes it to 'B'.

3.    The printf function then prints the resulting character, 'B', preceded by a newline character.    

 

 


 

5. Write a C program to dynamically allocate memory for an array to store 10 integers and display the first 5 out of them.

Answer: C program:

#include <stdio.h>

#include <stdlib.h> // Required for dynamic memory allocation functions (malloc, free)

 

int main() {

    int* ptr; // Pointer to hold the base address of the dynamically allocated memory

    int n = 10; // Number of integers to store

 

    // Dynamically allocate memory for 10 integers (10 * sizeof(int) bytes)

    // malloc returns a void pointer, which is cast to an int pointer

    ptr = (int*)malloc(n * sizeof(int));

 

    // Check if memory allocation was successful

    if (ptr == NULL) {

        printf("Error! Memory allocation failed.\n");

        return 1; // Exit the program if allocation fails

    }

 

    // Initialize the array with some values for demonstration

    printf("Initializing the array with values 1 through 10:\n");

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

        *(ptr + i) = i + 1; // Assign value (i + 1) to the i-th element

        // Alternatively, you can use array syntax: ptr[i] = i + 1;

    }

 

    // Display the first 5 elements of the array

    printf("\nDisplaying the first 5 elements:\n");

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

        printf("Element %d: %d\n", i, *(ptr + i));

        // Alternatively: printf("Element %d: %d\n", i, ptr[i]);

    }

 

    // Free the dynamically allocated memory

    // It's crucial to release the memory when it's no longer needed to prevent memory leaks

    free(ptr);

    ptr = NULL; // Best practice to set the pointer to NULL after freeing

 

    return 0;

}

Explanation of Key Parts:

1.    #include <stdlib.h>: This header file is necessary to use memory management functions like malloc() and free().

2.    int* ptr;: A pointer of type int is declared to store the starting address of the allocated memory block.

3.    int n = 10;: A variable n is defined to clearly indicate the size of the array (10 elements).

4.    ptr = (int*)malloc(n * sizeof(int));:

1.    sizeof(int) determines the size in bytes of a single integer on your system (typically 4 bytes).

2.    n * sizeof(int) calculates the total bytes required for 10 integers.

3.    malloc() allocates this block of memory from the heap and returns a pointer to the first byte of the allocated space.

4.    (int*) casts the returned void pointer to an integer pointer type.

                Error Checking (if (ptr == NULL)): It is good practice to check if malloc successfully allocated the memory. If it returns NULL, it means memory allocation failed (e.g., due to insufficient memory).

                Accessing Elements:

0.    We use pointer arithmetic *(ptr + i) or the more familiar array subscript notation ptr[i] to access and assign values to the individual elements within the allocated memory block.

                free(ptr);: This is the most important step after you are done using the dynamically allocated memory. free() deallocates the memory previously allocated by malloc, preventing memory leaks.

                ptr = NULL;: Setting the pointer to NULL after freeing ensures it doesn't accidentally point to the deallocated memory (a "dangling pointer"). 

OUTPUT

The program compiles and runs the provided C code, which demonstrates dynamic memory allocation using malloc

The output will be:

Initializing the array with values 1 through 10:

 

Displaying the first 5 elements:

Element 0: 1

Element 1: 2

Element 2: 3

Element 3: 4

Element 4: 5

6. Write a C program to dynamically allocate memory for an array to store runs scored by Virat Kohli in the last ten ODI cricket matches. Write a function to find the maximum one.

Answer:

This C program uses malloc to dynamically allocate memory for 10 integers, stores runs scored by Virat Kohli, and finds the maximum value using a function. The memory is freed after use.  C program:

 

#include <stdio.h>

#include <stdlib.h>

 

// Function to find the maximum run scored

int findMaxRun(int *runs, int size) {

    int max = runs[0]; // Initialize max with the first run

    for (int i = 1; i < size; i++) {

        if (runs[i] > max) {

            max = runs[i]; // Update max if a higher run is found

        }

    }

    return max;

}

 

int main() {

    int *runs;

    int size = 10; // Last ten ODI matches

    int maxRun;

 

    // Dynamically allocate memory for the array

    runs = (int *)malloc(size * sizeof(int));

 

    // Check if memory allocation was successful

    if (runs == NULL) {

        printf("Memory allocation failed. Exiting...\n");

        return 1;

    }

 

    // Input runs scored in the last 10 matches

    printf("Enter runs scored in the last 10 matches:\n");

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

        scanf("%d", &runs[i]);

    }

 

    // Find the maximum run scored using the function

    maxRun = findMaxRun(runs, size);

 

    // Display the maximum run scored

    printf("Maximum run scored by Virat Kohli in the last 10 matches: %d\n", maxRun);

 

    // Free the dynamically allocated memory

    free(runs);

 

    return 0;

}

Explanation

·         malloc: The malloc function is used to allocate memory for 10 integer elements (10 * sizeof(int)) at runtime.

·         Input: The program prompts the user to enter 10 integers, representing runs, and stores them in the allocated memory.

·         findMaxRun: This function iterates through the array and compares each element to find the highest value.

·         free: The free() function is called to release the allocated memory back to the system, preventing memory leaks. 

 

OUTPUT:

 

The provided C program prompts for 10 integers (runs), stores them in dynamically allocated memory, calculates the maximum value, and prints the result. Based on the code, here is an example execution: 

Input:

text

Enter runs scored in the last 10 matches:

50 68 102 45 78 93 55 120 35 84

Output:

text

Maximum run scored by Virat Kohli in the last 10 matches: 120

Note: The actual output will depend on the 10 integers entered by the user.

7. Write a C program and define a function that takes the length of your name as an input parameter and then allocates memory dynamically to store your name. Write another function to display the name.

 

Answer:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// Function to dynamically allocate memory for the name
char* allocateAndStoreName(int nameLength) {
    // Allocate memory dynamically for the name (length + 1 for the null terminator)
    char* name = (char*)malloc((nameLength + 1) * sizeof(char));
 
    // Check if memory allocation was successful
    if (name == NULL) {
        printf("Memory allocation failed. Exiting...\n");
        exit(1); // Exit the program if allocation fails
    }
 
    return name;
}
 
// Function to display the name
void displayName(const char* name) {
    if (name != NULL) {
        printf("The stored name is: %s\n", name);
    } else {
        printf("No name to display (pointer is NULL).\n");
    }
}
 
int main() {
    int length;
    char* myName;
 
    // Prompt the user for the length of their name
    printf("Enter the length of your name: ");
    if (scanf("%d", &length) != 1 || length <= 0) {
        printf("Invalid length entered.\n");
        return 1;
    }
 
    // Clear the input buffer after reading the integer
    while (getchar() != '\n');
 
    // Allocate memory using the defined function
    myName = allocateAndStoreName(length);
 
    // Prompt the user to enter their name
    printf("Enter your name: ");
    // Read the name from the user, ensuring it fits within the allocated size
    // Use fgets to read the string safely, length + 1 is the buffer size
    fgets(myName, length + 1, stdin);
 
    // Remove the trailing newline character that fgets might have captured
    // if the input was exactly the length + a newline
    myName[strcspn(myName, "\n")] = 0;
 
 
    // Display the name using the defined function
    displayName(myName);
 
    // Free the dynamically allocated memory
    free(myName);
    myName = NULL; // Best practice to set the pointer to NULL after freeing
 
    return 0;
}

 

OUTPUT:

The program takes user input for the length of a name, allocates memory dynamically, reads the name, displays it, and then frees the memory. The specific output depends on the user's input. 

Here are two examples of how the program would run:

 

Example 1: User enters "Alice"

text

Enter the length of your name: 5

Enter your name: Alice

The stored name is: Alice

 

Example 2: User enters "John Doe"

text

Enter the length of your name: 8

Enter your name: John Doe

The stored name is: John Doe

 

Example 3: User enters an invalid length (e.g., 0)

text

Enter the length of your name: 0

Invalid length entered.

 

Example 4:

Enter the length of your name: 5

Enter your name: Baburam Saikia

The stored name is: Babur


8. Write a C program to store some integer variables in an array. Then write functions to the following.

1. To calculate the number of even numbers in the array.

2. To dynamically allocate memory to a new array to store only the even numbers.

3. To copy the even numbers from the first array to the second one.

 

Sample run:

First array

2 4 0 9 1 9 8 6

Second array

2 4 0 8 6

 

Answer:

 

 

8. C Program to Handle Even Numbers in an Array

Step 1: Define the function to count even numbers

We'll create a function countEven that iterates through the array and counts how many elements are even.

 

int countEven(int arr[], int size) {

    int count = 0;

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

        if (arr[i] % 2 == 0) {

            count++;

        }

    }

    return count;

}

 

 

 

Step 2: Define the function to allocate memory and copy even numbers

We'll create a function copyEven that dynamically allocates memory for a new array using malloc based on the count from the previous step, and then copies the even numbers into it.

 

int* copyEven(int arr[], int size, int* newSize) {

    *newSize = countEven(arr, size);

    int* evenArr = (int*)malloc(*newSize * sizeof(int)); // Dynamically allocate memory

    if (evenArr == NULL) {

        // Handle memory allocation failure

        return NULL;

    }

 

    int j = 0;

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

        if (arr[i] % 2 == 0) {

            evenArr[j] = arr[i];

            j++;

        }

    }

    return evenArr;

}

 

 

Step 3: Combine into a complete program with a main function

Here is the full C program incorporating the functions and a main function to demonstrate the sample run.

#include <stdio.h>

#include <stdlib.h> // Required for malloc and free

 

int countEven(int arr[], int size) {

    int count = 0;

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

        if (arr[i] % 2 == 0) {

            count++;

        }

    }

    return count;

}

 

int* copyEven(int arr[], int size, int* newSize) {

    *newSize = countEven(arr, size);

    int* evenArr = (int*)malloc(*newSize * sizeof(int));

    if (evenArr == NULL) {

        printf("Memory allocation failed\n");

        exit(1);

    }

 

    int j = 0;

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

        if (arr[i] % 2 == 0) {

            evenArr[j] = arr[i];

            j++;

        }

    }

    return evenArr;

}

 

int main() {

    int firstArr[] = {2, 4, 0, 9, 1, 9, 8, 6};

    int firstSize = sizeof(firstArr) / sizeof(firstArr[0]);

    int secondSize;

 

    printf("First array:\n");

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

        printf("%d ", firstArr[i]);

    }

    printf("\n");

 

    int* secondArr = copyEven(firstArr, firstSize, &secondSize);

 

    printf("Second array:\n");

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

        printf("%d ", secondArr[i]);

    }

    printf("\n");

 

    free(secondArr); // Free dynamically allocated memory

    return 0;

}

 

The complete C program provided above fulfills all the requirements of the problem, including functions to count even numbers, dynamically allocate memory, and copy the even numbers to the new array.

 

 

 

 

 

 

Or:

 

#include <stdio.h>

#include <stdlib.h> // Required for malloc and free

 

// Function to calculate the number of even numbers in an array

int countEven(int arr[], int size) {

    int count = 0;

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

        if (arr[i] % 2 == 0) {

            count++;

        }

    }

    return count;

}

 

// Function to dynamically allocate memory and copy even numbers

int* copyEven(int arr[], int size, int *newSize) {

    *newSize = countEven(arr, size);

 

    // Dynamically allocate memory for the new array [9]

    int* evenArr = (int*)malloc(*newSize * sizeof(int));

 

    if (evenArr == NULL) {

        printf("Memory allocation failed.\\n");

        exit(1);

    }

 

    // Copy even numbers from the first array to the second one [2, 9]

    int j = 0;

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

        if (arr[i] % 2 == 0) {

            evenArr[j] = arr[i];

            j++;

        }

    }

    return evenArr;

}

 

int main() {

    // Store some integer variables in an array

    int firstArray[] = {2, 4, 0, 9, 1, 9, 8, 6};

    int originalSize = sizeof(firstArray) / sizeof(firstArray[0]);

    int secondArraySize;

 

    // Call the function to dynamically allocate and copy even numbers

    int* secondArray = copyEven(firstArray, originalSize, &secondArraySize);

 

    // Print the first array

    printf("First array:\\n");

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

        printf("%d ", firstArray[i]);

    }

    printf("\\n");

 

    // Print the second array

    printf("Second array:\\n");

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

        printf("%d ", secondArray[i]);

    }

    printf("\\n");

 

    // Free the dynamically allocated memory

    free(secondArray);

 

    return 0;

}

 

 

OUTPUT:

 

The program compiles and runs correctly. 

The output of the C program is:

First array:

2 4 0 9 1 9 8 6

Second array:

2 4 0 8 6

The even numbers are extracted from the firstArray and stored in the dynamically allocated secondArray. Note that 9 and 1 are odd numbers and are therefore omitted from the secondArray. 


 

9. Write a C program to store some integer variables in an array. Then write functions to

the following.

1. To calculate the number of non-zero elements that are divisible by 3.

2. To dynamically allocate memory to a new array to store only those elements.

3. To copy the selected elements from the first array to the second one.

4. To calculate the summation of these elements.

Sample run:

First array

2 4 0 9 1 9 8 6

Second array

9 9 6

 

Summation: 24

 

Answer:

 

This C program follows your logic requirements by using a two-pass approach: first identifying the count to allocate exactly the right amount of memory, and then populating the new array.

C

#include <stdio.h>

#include <stdlib.h>

 

// 1. Function to count non-zero elements divisible by 3

int countDivisibleByThree(int arr[], int size) {

    int count = 0;

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

        if (arr[i] != 0 && arr[i] % 3 == 0) {

            count++;

        }

    }

    return count;

}

 

// 2 & 3. Function to allocate memory and copy elements

int* getFilteredArray(int original[], int size, int newSize) {

    if (newSize == 0) return NULL;

 

    // Dynamically allocate memory

    int* newArr = (int*)malloc(newSize * sizeof(int));

   

    if (newArr == NULL) {

        printf("Memory allocation failed!\n");

        return NULL;

    }

 

    int j = 0;

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

        if (original[i] != 0 && original[i] % 3 == 0) {

            newArr[j] = original[i];

            j++;

        }

    }

    return newArr;

}

 

// 4. Function to calculate summation

int calculateSum(int arr[], int size) {

    int sum = 0;

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

        sum += arr[i];

    }

    return sum;

}

 

int main() {

    int firstArray[] = {2, 4, 0, 9, 1, 9, 8, 6};

    int size = sizeof(firstArray) / sizeof(firstArray[0]);

 

    // Step 1: Count

    int filteredCount = countDivisibleByThree(firstArray, size);

 

    // Step 2 & 3: Allocate and Copy

    int* secondArray = getFilteredArray(firstArray, size, filteredCount);

 

    // Output First Array

    printf("First array\n");

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

        printf("%d ", firstArray[i]);

    }

 

    // Output Second Array

    printf("\nSecond array\n");

    if (secondArray != NULL) {

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

            printf("%d ", secondArray[i]);

        }

 

        // Step 4: Summation

        int sum = calculateSum(secondArray, filteredCount);

        printf("\n\nSummation:\n%d\n", sum);

    } else {

        printf("No elements found or memory failed.\n");

    }

 

    // Clean up dynamic memory

    free(secondArray);

 

    return 0;

}


Key Logic Points

·         Non-Zero Check: The condition arr[i] != 0 && arr[i] % 3 == 0 ensures we skip the zeros, as $0 \pmod 3$ is technically $0$ in C, but your requirements specifically asked for non-zero elements.

·         Dynamic Allocation: We use malloc based on the filteredCount. This is more memory-efficient than creating a second array of the same size as the first.

·         Summation: The sum function only iterates through the secondArray, ensuring we only total the numbers that met our criteria.

Would you like me to show you how to handle the case where the user enters the array values manually through the console?