Define a pointer and explain the address and dereference operators.
5 marks
Answer in brief
A pointer variable stores a pointer value. A valid object pointer can be used to access an object indirectly.
Declaration
int number = 10;
int *p = &number;
Address operator
&number produces the address of number. The declaration stores that address in p. The star in int *p declares a pointer type; it does not read the object at that point. The pointer and the pointed-to integer are separate objects.
Dereference operator
In an expression, *p accesses the integer to which p points. Reading *p initially gives 10. Assigning *p = 25 changes number itself to 25. It does not change which object p identifies.
Example trace
The program first prints the value through *p. It then assigns through *p and prints number. The second output is 25, demonstrating that direct access through number and indirect access through p reach the same object.
Important points
Initialise a pointer before using its stored value.
Dereference only a pointer that identifies a suitable live object.
Do not dereference NULL, a one-past-end position or an invalid pointer.
Use %p with an object pointer converted to void * when displaying an address; the displayed form depends on the implementation.
Complexity
A direct pointer dereference and assignment to a fixed-size object take O(1) work in the usual model. A pointer does not automatically allocate the object it is expected to identify.
Diagram or flowchart
Define a pointer and explain the address and dereference operators. · Download diagram
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int main(void)
{
int number = 10;
int *p = &number;
printf("Before = %d\n", *p);
*p = 25;
printf("After = %d\n", number);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Before = 10
After = 25
Related exam questions
Related questions in the pointer basics category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain pointer types, void pointers and null pointers.
5 marks
Answer in brief
A pointer’s type describes the kind of object or function it can identify and the operations permitted through it.
Typed object pointers
int * is a pointer to int.
double * is a pointer to double.
char * can identify character storage.
The pointed-to type controls access and the step used by valid pointer arithmetic.
Void pointer
void * is a generic object-pointer type. In C, an object pointer can be converted to void * and back to its original object-pointer type, preserving the comparison result with the original. A void pointer cannot be directly dereferenced to obtain an object value, and standard C does not define arithmetic on void *. Convert it to the appropriate object-pointer type before suitable access.
Null pointer
NULL is a macro usable as a null pointer constant. A null pointer can mark that no object has been selected or allocation has failed. It is not safe to dereference. Do not assume its stored bit pattern or printed form must be all zeroes; use the language’s null-pointer operations.
Example
The sample lets a void * hold the address of an int, then converts it back to int * and reads the integer. Both pointers identify the original live int object. This does not justify converting an arbitrary address to an unrelated type and reading it.
Important points
C does not require every pointer type to have the same size as int or even the same size as every other pointer type. Function pointers have their own types; void * is not a portable universal container for function pointers. Correct type, alignment and lifetime all matter.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int main(void)
{
int value = 12;
void *generic = &value;
int *p = generic;
printf("Value = %d\n", *p);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Value = 12
Related exam questions
Related questions in the pointer basics category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain how pointer arguments allow a function to modify caller data.
5 marks
Answer in brief
A function can receive a pointer to a caller’s object and modify the object through that pointer.
Function interface
void set_value(int *p, int value);
Working
The caller passes &number and the new integer value.
The parameter p receives a copy of the address.
The assignment *p = value changes the caller’s number object.
Example trace
number begins at 10. set_value(&number, 30) gives p the address of number and gives value the integer 30. The function checks p against NULL, then writes through it. After returning, main prints 30 because number itself was changed.
Value versus target
Changing p to NULL inside the function would only change the local pointer parameter. It would not replace a caller’s pointer variable. Changing *p updates the target. To update a caller’s pointer object, an additional level of indirection can be used, as shown in the pointer-to-pointer topic.
Validity
A non-null test is useful but does not prove every pointer is valid. The caller must still provide a pointer to a live, writable int object. A dangling pointer can be non-null. The example passes the address of a local object whose lifetime includes the complete call.
Complexity
The function performs a fixed comparison and at most one fixed-size assignment. Time and auxiliary space are O(1). Passing an address does not require copying every byte of a larger object that might be reached through it.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
void set_value(int *p, int value)
{
if (p != NULL) { *p = value; }
}
int main(void)
{
int number = 10;
set_value(&number, 30);
printf("Number = %d\n", number);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Number = 30
Related exam questions
Related questions in the pointer function arguments category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q9(b) · 4 marks
Explain passing pointers to a function, with examples.
A pointer to a pointer identifies another pointer object. It is useful when a function must update a caller’s pointer value.
Basic declarations
int number = 10;
int *p = &number;
int **pp = &p;
Two access levels
pp identifies p. Therefore *pp refers to p itself, and **pp reaches number. These levels must be interpreted in order. A declaration of int ** does not automatically create either a pointer target or an int target; all objects must already exist or be allocated appropriately.
Function example
redirect receives &p and &second. Its parameter slot identifies main’s pointer p. Assigning *slot = target changes p to identify second. After the call, *p reads 20. The function has changed which integer p points at, rather than assigning 20 into the first integer.
Why a single pointer parameter is insufficient
If the function received only a copy of p as int *local, assigning local = &second would change only local. Passing the address of p allows the function to reach and assign main’s actual pointer object. The argument is still passed by value: the copied value is now a pointer to that pointer object.
Precautions and complexity
The slot must identify a live, writable int * object. A null check alone does not prove a non-null pointer is valid. The supplied target must also remain alive while it is used. The sample uses two local ints and one pointer during the same main call, so all lifetimes are suitable. Its fixed assignments use O(1) time and auxiliary space.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
void redirect(int **slot, int *target)
{
if (slot != NULL) { *slot = target; }
}
int main(void)
{
int first = 10, second = 20;
int *p = &first;
redirect(&p, &second);
printf("Selected = %d\n", *p);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Selected = 20
Related exam questions
Related questions in the pointer function arguments category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q9(b) · 4 marks
Explain passing pointers to a function, with examples.
A function pointer identifies a function with a compatible type and allows that function to be selected or passed as a value.
Declaration and assignment
int (*operation)(int, int) = add;
Meaning
operation can identify a function receiving two ints and returning int. The function name add supplies a suitable function pointer in this expression. Calling operation(4, 6) or (*operation)(4, 6) invokes the selected function. The function must have a compatible type; an arbitrary cast does not make an incompatible call safe.
Callback-style example
apply receives a function pointer named op along with a and b. It returns op(a, b). main supplies add for one call and subtract for another. Thus apply keeps the general calling step while the caller chooses the operation. The output is 10 for addition and -2 for subtraction.
Uses
Select an arithmetic operation or menu action.
Let a general algorithm call a caller-supplied comparison or processing function.
Keep a table of compatible operations when that makes the design clearer.
Precautions
Do not call a null or invalid function pointer. An object pointer and a function pointer are not interchangeable portable storage formats. The sample always passes real functions with exactly matching signatures.
Complexity
An indirect call does not change the algorithmic growth of the selected function. With the fixed-size addition or subtraction shown, each application takes O(1) time and O(1) extra space. More complex callbacks can perform more work.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int apply(int (*op)(int, int), int a, int b)
{
return op(a, b);
}
int main(void)
{
printf("Add = %d\n", apply(add, 4, 6));
printf("Subtract = %d\n", apply(subtract, 4, 6));
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Add = 10
Subtract = -2
Related exam questions
Related questions in the pointer function arguments category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q9(b) · 4 marks
Explain passing pointers to a function, with examples.
Explain the relationship between pointers and one-dimensional arrays.
5 marks
Answer in brief
An array contains its elements, while a pointer can identify an element. Their close relationship makes pointer-based traversal possible, but they are not identical types.
Example
int a[3] = {4, 5, 6};
int *p = a;
Indexed and indirect access
For a valid index i, a[i] means *(a + i). With p pointing at the first element, p[i] and *(p + i) also access that element. The sample visits all three values through p and prints 4, 5 and 6.
Important differences
The array declaration reserves storage for all three ints; declaring p reserves only a pointer object.
p can be assigned another compatible address. The array name is not a modifiable pointer variable that can be incremented.
sizeof a gives the whole array size where the actual declaration is visible, while sizeof p gives the pointer size.
&a has a pointer-to-array type, which differs from the pointer-to-element type produced by a in most expressions.
Function connection
A parameter written int a[] adjusts to int *a. That parameter does not retain the caller’s complete array length. Pass a suitable count separately and keep every access within the actual array.
Complexity
A direct valid access takes O(1) time in the usual model. Traversing n elements through a pointer still takes O(n): pointer notation does not remove the need to visit every element. This traversal uses O(1) auxiliary space beyond the array.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int main(void)
{
int a[3] = {4, 5, 6};
int *p = a;
for (int i = 0; i < 3; ++i) { printf("%d\n", *(p + i)); }
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
4
5
6
Related exam questions
Related questions in the pointers arrays category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
June 2022 · Q4(b) · 8 marks
What is a pointer? Write a C program to sum array elements using a pointer.
Explain valid pointer arithmetic and pointer subtraction.
5 marks
Answer in brief
Pointer arithmetic moves between elements of the same array. Its step is measured in elements of the pointed-to type.
Addition and subtraction
If p identifies a[i], p + k can identify a[i + k] when the result is within that array or one past it. p - k moves backwards under the same restriction. p++ updates the pointer to the next element; (*p)++ instead increments the pointed-to value, when that value is writable and the operation is valid.
Pointer difference
Subtracting two suitable pointers into the same array gives their distance in elements, of type ptrdiff_t. The sample sets first to a[0] and last to a[3], so last - first gives 3. Use %td to print ptrdiff_t. The difference must be representable in that type.
One-past-end rule
a + n can be formed for an array of n elements, but it must not be dereferenced. This permits a loop that stops when p equals the end pointer. Do not continue arithmetic beyond that position, even if an unrelated object happens to follow in memory.
Invalid operations
Adding two pointers is not a defined pointer operation.
Do not subtract pointers into unrelated arrays.
Do not assume ordering comparisons between unrelated objects follow their displayed addresses.
Standard C does not support arithmetic on function pointers or void *.
Complexity
A valid pointer step or difference is O(1) in the usual machine model. A loop that advances once per element still takes O(n) time and O(1) auxiliary space. The rules are about array membership, not merely whether an address appears numerically nearby.
Diagram or flowchart
Explain valid pointer arithmetic and pointer subtraction. · Download diagram
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <stddef.h>
int main(void)
{
int a[4] = {10, 20, 30, 40};
int *first = a, *last = a + 3;
printf("Next = %d\n", *(first + 1));
printf("Distance = %td\n", last - first);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Next = 20
Distance = 3
Related exam questions
Related questions in the pointer arithmetic category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain an array of pointers with a string example.
5 marks
Answer in brief
An array of pointers stores several pointer values. Each element can identify a different object or string.
Declaration
const char *names[3] = {"C", "Python", "Java"};
Meaning
names[0] points to the first character of "C", names[1] to "Python" and names[2] to "Java". Each names[i] is a pointer, not an entire fixed-width row of characters. The string literals exist separately and must not be modified.
Access and output
puts(names[i]) displays the selected null-terminated string and adds a newline. names[i][j] can read the j-th character when that index is valid for the selected string. The null terminator belongs to each separate string; it does not terminate the array of pointers itself.
Comparison with a character matrix
char names[3][10] reserves three rows of ten characters, including room for each terminator. const char *names[3] reserves three pointers that identify existing strings of potentially different lengths. The layouts and parameter types differ. An array of pointers is not automatically one contiguous character matrix.
Uses and complexity
Pointer arrays are useful for menus, labels or lists of independently stored strings. Selecting names[i] takes O(1) work. Displaying all characters takes time proportional to the total displayed string length, plus the list traversal. The pointer array needs storage for three pointers in this fixed example; the strings have their own storage.
Important point
The const applies to the characters reached through each pointer. It does not by itself make each pointer element impossible to reassign to another suitable string.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int main(void)
{
const char *names[3] = {"C", "Python", "Java"};
for (int i = 0; i < 3; ++i) { puts(names[i]); }
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
C
Python
Java
Related exam questions
Related questions in the array of pointers category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain pointers to rows of a two-dimensional array.
5 marks
Answer in brief
A two-dimensional array is an array of row arrays. Its usual conversion produces a pointer to its first row, not a pointer to pointer.
Declaration
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = a;
Row and element access
p identifies the first row. p + 1 identifies the next row because its pointed-to type is an array of three ints. p[1][2] reads 6. The equivalent form *(*(p + 1) + 2) first selects the second row and then its third element.
Why the width matters
The compiler needs the row width to calculate the correct step between rows. A function parameter int a[][3] adjusts to this pointer-to-row type. Passing a logical column count does not change an actual object declared with a different fixed row width.
Difference from int **
An int ** identifies an int * object. A rectangular int a[2][3] instead contains ints grouped into row arrays; it does not contain an intermediate array of int * values. Casting between these layouts does not rearrange the storage and does not justify incompatible access.
Bounds and complexity
Both row and column indices must be valid. a[0][3] is not a permitted replacement for a[1][0]. Reading a fixed valid element takes O(1) work. Traversing all r × c elements takes O(rc) time and O(1) auxiliary space beyond the matrix. The example reads one element and displays its value.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = a;
printf("Selected = %d\n", *(*(p + 1) + 2));
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Selected = 6
Related exam questions
Related questions in the pointers arrays category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
June 2022 · Q4(b) · 8 marks
What is a pointer? Write a C program to sum array elements using a pointer.
Explain dynamic memory allocation and its main functions.
5 marks
Answer in brief
Dynamic allocation requests storage while a program is running. The program manages the useful lifetime of that storage explicitly.
Main functions
malloc requests a number of bytes without initialising their contents.
calloc allocates space for a count of equal-sized objects and sets the allocated bytes to zero.
realloc changes the size of an existing allocated block, possibly moving it.
free releases an allocated block when it is no longer needed.
Typical sequence
Determine a valid element count and check that its byte-size calculation cannot overflow.
Request storage using a suitable allocation function.
Check for NULL before using the result.
Initialise the required elements and use only valid positions.
Release storage exactly once when ownership ends.
Example size expression
int *p = malloc(n * sizeof *p);
Meaning and precautions
sizeof *p gives the size of the intended element without evaluating a dereference in this ordinary int case. In C, the returned void * can be assigned to int * without a cast. The allocated object is not automatically released when the local pointer variable leaves scope. Losing the last useful pointer to a needed allocation can cause a memory leak.
Space and time
Storage for n integers is proportional to n, giving O(n) allocated space. Initialising or reading all n elements takes O(n) work. C does not specify one algorithm or universal Big-O bound for malloc itself, so do not claim that every allocation call is guaranteed constant time. The following topics supply complete examples.
Diagram or flowchart
Explain dynamic memory allocation and its main functions. · Download diagram
Related exam questions
Related questions in the dynamic memory category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Compare malloc and calloc with a complete example.
5 marks
Answer in brief
Both functions obtain allocated storage, but their argument forms and initialisation differ.
Malloc
int *a = malloc(n * sizeof *a);
Calloc
int *b = calloc(n, sizeof *b);
Working
malloc takes one byte-count argument. calloc takes an element count and an element size. A successful call returns a suitably aligned pointer for the ordinary int objects used here. A failed non-zero request returns NULL. Always check the result before access.
Example trace
The program requests three ints with each function. It explicitly fills the malloc block with 1, 2 and 3, so their sum is 6. It then reads the calloc-created int elements, whose initial values are zero, and prints a sum of 0. Both blocks are freed.
Important distinctions
The all-zero-byte rule is not a universal promise of the floating value 0.0 or a null pointer representation for every type. The example specifically uses int. For arbitrary counts, validate multiplication before forming a malloc byte count; do not allow size_t arithmetic to wrap. This fixed request has a small known count.
Failure and complexity
If either allocation fails, the sample frees any successful allocation before returning. free(NULL) is permitted. Filling and summing n elements requires O(n) element work, and the allocated storage is O(n). Allocator internals have implementation-dependent costs; the traversal analysis is separate.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t n = 3;
int *a = malloc(n * sizeof *a);
int *b = calloc(n, sizeof *b);
if (a == NULL || b == NULL) {
free(a); free(b); puts("Allocation failed"); return 1;
}
int sum_a = 0, sum_b = 0;
for (size_t i = 0; i < n; ++i) {
a[i] = (int)i + 1;
sum_a += a[i]; sum_b += b[i];
}
printf("Malloc sum = %d, calloc sum = %d\n", sum_a, sum_b);
free(a); free(b);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Malloc sum = 6, calloc sum = 0
Related exam questions
Related questions in the dynamic memory category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain safe use of realloc and free with an example.
5 marks
Answer in brief
realloc changes an allocation’s size. free releases storage obtained through the allocation family.
Safe pattern
int *temporary = realloc(p, new_count * sizeof *p);
if (temporary == NULL) {
/* p still identifies the original block for this non-zero request */
} else {
p = temporary;
}
What is preserved
On success, the old contents are preserved up to the smaller of the old and new sizes. A larger block’s added bytes are not automatically initialised. The allocation may move. The old pointer must no longer be used after a successful realloc, even when the returned address appears unchanged.
Example trace
The sample allocates two ints and stores 1 and 2. It requests space for four ints using a temporary pointer. After success, it stores 3 and 4 in the new positions and displays 1, 2, 3, 4. If growth fails, it frees the still-valid original block and exits.
Free and ownership
Pass free a valid currently allocated base pointer, or NULL. Do not free an interior element pointer, an automatic array or the same allocation twice. After freeing p, assigning p = NULL avoids retaining a dangling value in that variable. Other aliases are not automatically changed.
Limits and complexity
Use a validated non-zero new size and check multiplication for overflow. This lesson avoids the special zero-size realloc cases. A reallocation may need to copy retained data; its allocator cost is implementation-dependent. The explicit initialisation and printing of n values take O(n) work, and storage for n ints is O(n).
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p = malloc(2 * sizeof *p);
if (p == NULL) { puts("Allocation failed"); return 1; }
p[0] = 1; p[1] = 2;
int *temporary = realloc(p, 4 * sizeof *p);
if (temporary == NULL) { free(p); puts("Allocation failed"); return 1; }
p = temporary;
p[2] = 3; p[3] = 4;
for (int i = 0; i < 4; ++i) { printf("%d\n", p[i]); }
free(p);
p = NULL;
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
1
2
3
4
Related exam questions
Related questions in the dynamic memory category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain uninitialised pointers, dangling pointers and memory leaks.
5 marks
Answer in brief
Pointer safety requires a valid target, correct bounds and a suitable lifetime. A pointer-looking value alone is not proof that access is allowed.
Uninitialised pointer
An ordinary automatic pointer declared without an initialiser does not contain a useful guaranteed pointer value. Do not read or dereference it. Initialise it to a valid address or a null pointer according to its intended state.
Dangling pointer
A pointer becomes unusable for target access when that object’s lifetime ends. Examples include a pointer to an automatic local array after its function returns and a pointer into a freed allocation. A non-null check does not establish that either target is still alive.
Memory leak
If the last useful pointer to an allocated block is lost before free, the program may no longer be able to release it. Overwriting p directly with a failed realloc result is a common source of this mistake. Use a temporary result for non-zero reallocation.
Out-of-bounds access
An index or pointer must remain within the appropriate object. A formed one-past-end pointer is not a valid element to dereference. String routines also require reachable termination and enough writable destination capacity. Merely changing a pointer’s type does not create a larger object.
Good practice
State who owns each allocation and who must free it.
Check allocation results and relevant input limits.
Release the allocation exactly once; do not free an interior pointer.
Clear a local pointer after free when it helps avoid later use, while remembering aliases remain invalid.
Return pointers only to storage with a suitable remaining lifetime.
Key distinction
These are correctness rules, not optional optimisations. An invalid access has undefined behaviour; passing a small test does not make the access valid.
Worked example: resize an array without losing its original address
A student stores three marks in a dynamically allocated array and later needs room for five. A successful realloc may move the block. For a non-zero requested size, a failed realloc returns a null pointer and leaves the original block allocated.
↔ Scroll horizontally on a small screen
The two possible resize results
Result
What happens to the data?
What should the program do?
Success
The first three integers are preserved; the added space is uninitialised
Assign the returned pointer to items, then initialise the two new elements
Failure
The original three-element block remains allocated
Keep its pointer for later use, or free it before returning
Common mistake
Writing items = realloc(items, ...) directly can overwrite the only useful pointer with a null pointer on failure. Save the result in a temporary pointer first. After success, use the returned pointer; any old aliases to the previous allocation must not be used, even if the returned address appears unchanged.
Complete C example
This example uses fixed sizes of three and five integers. It frees the original block if resizing fails because the program is about to exit.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *items = malloc(3 * sizeof *items);
if (items == NULL) {
puts("Allocation failed");
return 1;
}
for (int i = 0; i < 3; ++i) { items[i] = (i + 1) * 10; }
printf("Before: %d %d %d\n", items[0], items[1], items[2]);
int *temporary = realloc(items, 5 * sizeof *items);
if (temporary == NULL) {
/* The original block is still available through items. */
free(items);
puts("Resize failed");
return 1;
}
items = temporary;
items[3] = 40;
items[4] = 50;
printf("After: %d %d %d %d %d\n",
items[0], items[1], items[2], items[3], items[4]);
free(items);
items = NULL;
return 0;
}
Output when both allocations succeed
Before: 10 20 30
After: 10 20 30 40 50
The program writes elements 3 and 4 before reading them. Increasing capacity does not automatically give those new integers useful values. If a real program accepts a size from input, it must also check that the size multiplication fits in size_t before allocating.
Related exam questions
Related questions in the dynamic memory category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
Explain C strings, null termination and character arrays.
5 marks
Answer in brief
A C string is a sequence of character bytes terminated by a null character. A character array is a string only when the required terminator is present within its valid storage.
Declaration
char word[] = "Code";
/* elements: C, o, d, e, \0 */
Length and capacity
word contains five char elements, so sizeof word is 5 C bytes. Its string length is 4 because strlen counts characters before the terminator. A destination for four visible ASCII characters needs at least five char positions. The terminator occupies space even though it is not printed as part of the text.
Array versus pointer
char word[] = "Code"; creates a writable array initialised from the literal. const char *label = "Code"; creates a pointer to a string literal that must not be modified. The array and the pointer have different sizes and assignment rules.
Important examples
char a[4] = {'C', 'o', 'd', 'e'} has no terminator and must not be used as a string by strlen or puts.
An empty string contains a terminator at its first position and has length zero.
The null character is not the same as a null pointer.
Complexity and text
Finding the length with strlen requires examining bytes until the terminator, giving O(n) work in the ordinary analysis. A known-index character read is O(1). These introductory examples process ordinary text bytes; a byte count is not necessarily the count of displayed Unicode characters in a multibyte encoding.
Diagram or flowchart
Explain C strings, null termination and character arrays. · Download diagram
This example uses values already written in the program.
Output
Length = 4, array bytes = 5
Related exam questions
Related questions in the string basics category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q4(a) · 5 marks
Differentiate a null-terminated string and a fixed-length string.
Paper P06 · page 1
January/February 2024 · Q4(b) · 6 marks
Compare character arrays and string literals. Explain strings as arrays of characters.
Explain whole-line string input using fgets and safe newline handling.
5 marks
Answer in brief
fgets reads at most one less than the supplied positive capacity and adds a null terminator when successful. It is useful for whole-line input, including spaces.
Basic form
char line[80];
if (fgets(line, sizeof line, stdin) != NULL) {
/* use the successfully read string */
}
Newline handling
If the newline fits, fgets stores it before the terminator. strchr(line, '\n') can locate it so that it can be replaced with '\0'. Do not simply delete the last stored character without checking: input can end without a newline.
Length limit
This complete example accepts at most 79 text bytes. Its helper reads a bounded first portion. If no newline was stored, it checks the next input character: a newline or end of input means the line fit exactly or ended naturally. A longer line is drained and rejected, preventing a truncated prefix from being accepted as the whole answer.
Important points
A failed read must be handled before treating the buffer as new input. gets must not be used because it cannot enforce the destination capacity and is not part of modern standard C. scanf("%s", ...) stops at whitespace and is not equivalent to whole-line input.
Complexity and assumptions
Reading and checking a line of n bytes takes O(n) work. This fixed buffer uses bounded storage; a general capacity-m version needs O(m) buffer space. The helper is for ordinary text without embedded null bytes, not arbitrary binary input.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <string.h>
int read_line(char s[], int capacity)
{
if (fgets(s, capacity, stdin) == NULL) { return 0; }
char *newline = strchr(s, '\n');
if (newline != NULL) { *newline = '\0'; return 1; }
int ch = getchar();
if (ch == '\n' || ch == EOF) { return 1; }
while ((ch = getchar()) != '\n' && ch != EOF) { }
return 0;
}
int main(void)
{
char line[80];
if (!read_line(line, 80)) { puts("Invalid or overlong input"); return 1; }
printf("Line: %s\n", line);
return 0;
}
Sample input and output
Input
Hello students
Output
Line: Hello students
Related exam questions
Related questions in the string basics category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q4(a) · 5 marks
Differentiate a null-terminated string and a fixed-length string.
Paper P06 · page 1
January/February 2024 · Q4(b) · 6 marks
Compare character arrays and string literals. Explain strings as arrays of characters.
Explain character pointers and const string parameters in functions.
5 marks
Answer in brief
A character pointer can identify the first byte of a string. Functions can use it to read characters or, for a writable target and suitable interface, modify them.
Read-only interface
void show(const char *text);
Working
The caller supplies a pointer to the first character. show reads text until its null terminator through puts. The const-qualified character access prevents the function from writing text[0] through this parameter. The local pointer parameter itself is a copied pointer value.
String literal and array
A literal such as "Welcome" must not be modified. A writable array such as char name[] = "Student"; contains its own copy and can be changed within bounds. Both can be passed to a suitable reading function. Use const char * for a literal pointer so the intended reading-only use is clear.
Modification interface
A function that writes a string normally needs char * and a destination capacity. The pointer alone does not communicate how many positions are available. A function must not store beyond the capacity or leave a result unterminated when a string result is promised.
Return and lifetime
Returning a pointer is valid only when the target remains alive for its later use. Do not return the address of an ordinary automatic local character array. A pointer to caller-owned storage or a suitable lasting object requires a clearly stated lifetime and ownership agreement.
Complexity
Displaying n bytes takes O(n) output work. The pointer argument is small fixed-size state and does not copy the whole string. No new variable-length buffer is created by this example.
This example uses values already written in the program.
Output
Welcome
Related exam questions
Related questions in the string basics category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September 2023 · Q4(a) · 5 marks
Differentiate a null-terminated string and a fixed-length string.
Paper P06 · page 1
January/February 2024 · Q4(b) · 6 marks
Compare character arrays and string literals. Explain strings as arrays of characters.
Explain the main string library functions and their precautions.
5 marks
Answer in brief
The string.h header declares common operations on null-terminated strings and memory. Each function still requires valid arguments and sufficient storage.
Main functions
strlen(s) returns the number of bytes before the null terminator as size_t.
strcpy(destination, source) copies the source and its terminator.
strcat(destination, source) appends the source after the destination’s existing string.
strcmp(a, b) compares two strings and returns a negative, zero or positive value.
strchr(s, ch) locates the first matching character, or returns NULL when absent.
Capacity requirements
strcpy needs enough writable destination positions for source length plus one. strcat needs enough for both lengths plus one, and destination must already contain a valid string. These functions do not receive the destination’s capacity and cannot automatically grow it.
Overlap and bounded forms
strcpy and strcat require non-overlapping source and destination strings. For overlapping regions within one array, memmove is designed for moving a specified byte count safely. strncpy is not a general guarantee of termination: if the source is at least the specified count, the copied result is not automatically terminated.
Comparison and length
Use strcmp rather than == to compare text contents. Check only its result’s sign, not an assumed exact -1 or 1. Use %zu for the size_t returned by strlen. The length excludes the terminator, while required storage includes it.
Complexity
strlen and strcpy perform work proportional to the relevant string length. A single strcat must find the destination end and copy the source, giving O(d + s) work. strcmp examines a prefix until a difference or end is reached, up to O(min(m, n) + 1) byte comparisons. No growing auxiliary array is required by these basic operations.
Reference table
↔ Scroll horizontally on a small screen
String function requirements
Function
Purpose
Key requirement
strlen
Count bytes before terminator
Valid terminated source
strcpy
Copy with terminator
Enough capacity; no overlap
strcat
Append source
Terminated destination; enough space; no overlap
strcmp
Compare contents
Both sources terminated
strchr
Find character
Valid terminated source
memmove
Move specified byte count
Valid source/destination ranges; overlap allowed
Related exam questions
Related questions in the string functions category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September/October 2021 · Q7(b) · 8 marks
Describe string library functions with syntax and an example program.
Explain string initialisation, pointer assignment and copying into a character array.
5 marks
Answer in brief
A string can be used to initialise a character array, but replacing that array’s contents later requires copying characters into its writable storage.
Initialisation
char destination[20] = "Hello";
Copy after declaration
strcpy(destination, source) copies the characters and terminator when the destination is large enough and the regions do not overlap. The sample checks strlen(source) against sizeof destination before copying. It then prints the new contents C programming.
Pointer assignment
With const char *p = "Hello"; and p = "C";, only the pointer value changes. No characters are copied into the earlier string. This is valid pointer reassignment to another literal, but the literals themselves must not be modified.
Capacity example
A source of length 13 needs 14 char positions including the terminator. A 20-position destination can hold it. The comparison uses source length < destination capacity, not <=, because one position is reserved for the terminator.
Precautions
Do not apply sizeof destination as a capacity calculation when destination is merely an adjusted array parameter; pass the capacity separately. Do not assume strncpy always makes a usable string. If a manual copy is used, ensure it copies or writes the terminator too.
Complexity
Checking the length scans n source bytes, and copying scans them again. The total remains O(n), since a fixed number of linear passes is still linear. The copy writes into an existing buffer, with O(1) auxiliary space beyond that destination.
This example uses values already written in the program.
Output
C programming
Related exam questions
Related questions in the string functions category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September/October 2021 · Q7(b) · 8 marks
Describe string library functions with syntax and an example program.
Write a C function to extract a substring from a given position.
5 marks
Answer in brief
A substring is a consecutive part of a string. This example uses a zero-based start index and a requested character count.
Algorithm
Find the source length.
Reject start > length or count > length - start.
Reject a destination capacity of zero or count >= capacity.
Copy count characters beginning at start, then write the null terminator.
Worked example
For source "Programming", start 3 selects the first g. Taking count 4 copies g, r, a and m, producing "gram". The extracted text must receive its own terminator; it cannot depend on the next source character being null.
Boundary cases
start equal to the source length is valid only when count is zero. The result is an empty string. A request extending beyond the end is rejected. Testing count against length - start after validating start avoids adding start + count unnecessarily.
Storage rule
The sample uses a separate output array, so source and destination do not overlap. An interface should state its capacity and bounds clearly. C does not provide a special substring assignment operator that automatically allocates and terminates a result.
Complexity
The strlen pass takes O(n) for source length n. Copying k requested characters takes O(k), so the complete function is O(n + k), which is O(n) for a valid k <= n. Output storage needs O(k + 1) positions, while counters add O(1) auxiliary space. A function receiving a known validated source length could avoid scanning it again.
This example uses values already written in the program.
Output
gram
Related exam questions
Related questions in the substring operations category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
March/April 2023 · Q4(b) · 5 marks
Write a C program to insert a substring into a main string from a given position.
Explain string concatenation with a capacity-checked example.
5 marks
Answer in brief
Concatenation appends one string to another. strcat places the source characters after the destination’s current text and writes a final terminator.
Basic form
strcat(destination, source);
Example explanation
destination starts as "Hello " in a 30-position array. source is "students". Their lengths are 6 and 8, so the result has length 14 and requires 15 positions. The check confirms the source fits in the remaining space, then strcat produces "Hello students".
Capacity check
After confirming the existing destination is a valid string in its array, remaining capacity for new non-null bytes is capacity - used - 1. Comparing the added length with that remainder avoids an unchecked sum. The sample uses sizeof destination where the actual array is visible.
Precautions
The source and destination strings must not overlap.
The destination must contain its original terminator before strcat is called.
Do not append to a string literal or another non-writable target.
Never assume the function enlarges an array automatically.
Time and space complexity
For destination length m and source length n, strcat first locates the existing end and then copies the new text, giving O(m + n) work in the usual analysis. Length checks add only another fixed number of scans. Auxiliary space is O(1) beyond the destination buffer. Repeatedly appending many tiny pieces can cause repeated rescanning of a growing prefix and become quadratic in total work.
This example uses values already written in the program.
Output
Hello students
Related exam questions
Related questions in the string functions category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September/October 2021 · Q7(b) · 8 marks
Describe string library functions with syntax and an example program.
Explain string comparison using strcmp and why == is unsuitable for contents.
5 marks
Answer in brief
strcmp compares two null-terminated strings lexicographically, examining their contents rather than comparing pointer values.
Working
Compare corresponding bytes from the beginning.
Continue while they are equal and not at the end.
At the first difference, the unsigned character values determine the result’s sign.
If both strings end together without a difference, return zero.
Example
strcmp("Code", "Code") returns zero. The sample therefore prints Equal. Comparing a string with a longer string that starts with the same prefix treats the shorter completed prefix as earlier, since its null terminator is compared at that position.
Why not ==?
For pointer expressions referring to strings, == compares pointer values. Two pointers can identify different arrays containing equal text. Conversely, sharing one pointer does not perform a character-by-character text comparison. Use strcmp when the question is whether the stored text is equal.
Character rules
strcmp is case-sensitive and is not a general dictionary-order comparison for every language or locale. The exact encoding influences byte values. Do not hard-code an expected difference such as -32; inspect only the sign. For these introductory examples, use ordinary byte strings with valid termination.
Complexity
The function stops at the first difference or a terminating position. It may finish in O(1) for a first-byte difference, and needs up to O(min(m, n) + 1) byte comparisons for lengths m and n. It needs no growing output array, giving O(1) auxiliary space in the usual analysis.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[] = "Code", b[] = "Code";
int result = strcmp(a, b);
if (result == 0) { puts("Equal"); }
else if (result < 0) { puts("First is earlier"); }
else { puts("First is later"); }
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
Equal
Related exam questions
Related questions in the string functions category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September/October 2021 · Q7(b) · 8 marks
Describe string library functions with syntax and an example program.
Write a function to find a string’s length without strlen.
5 marks
Answer in brief
A manual length function scans from the first character until the terminating null character is reached.
Algorithm
Set length to zero.
While s[length] is not the null character, increment length.
Return length.
Worked trace
For "Code", index 0 contains C, index 1 contains o, index 2 contains d and index 3 contains e. Each adds one to length. At index 4 the null character is found, so the returned length is 4.
Return type
size_t is suitable for an object or string size. The sample obtains its declaration through stddef.h and prints it with %zu. It does not assume every valid string length fits int.
Precondition
The pointer must identify a valid string with a terminator reachable inside its permitted object. Without that terminator, the loop could read out of bounds; using a pointer or a library function does not repair an invalid string. A null pointer is not an empty string and cannot be passed here.
Boundary and text cases
An empty string starts with the terminator, so the loop runs zero times and returns zero. Spaces are counted like other non-null bytes. A multibyte encoded character may occupy several bytes, so this result is a byte-string length rather than a universal displayed-character count.
Complexity
For n non-null bytes, the loop makes n increments and a final stopping test. Time is O(n). It stores only the counter and pointer parameter, giving O(1) auxiliary space. The source is not modified or duplicated.
This example uses values already written in the program.
Output
Length = 4
Related exam questions
Related questions in the string functions category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
September/October 2021 · Q7(b) · 8 marks
Describe string library functions with syntax and an example program.
Write a function to insert a substring at a given string position.
5 marks
Answer in brief
Substring insertion places new text inside a writable string while preserving the text before and after the insertion position.
Algorithm
Find the main string and inserted string lengths.
Accept a zero-based position from 0 through the main length.
Check that main length, inserted length and terminator fit the destination capacity.
Move the suffix right with memmove, including its terminator.
Copy the inserted bytes into the gap.
Worked example
The main string is "CodeBhavya". Position 4 is immediately after Code. Inserting one space produces "Code Bhavya". The suffix Bhavya and the terminator move one position right before the space is copied into the gap.
Why memmove?
The source and destination suffixes are parts of the same array and can overlap. memmove supports that case. memcpy is used for the separate inserted string bytes here; the function requires the inserted source to be separate from the destination storage. It is not intended to insert an overlapping slice of itself.
Bounds
Position equal to the length appends text. Position zero inserts at the beginning. An empty inserted string leaves the contents unchanged. The function first checks length < capacity, then compares added length with capacity - length - 1, reserving a terminator position.
Complexity
Finding both lengths takes O(n + m). Moving the suffix takes at most O(n), and copying the new text takes O(m). Total work is O(n + m). The result needs capacity for n + m + 1 bytes; the explicit algorithm uses only fixed-size counters beyond that caller-owned buffer.
This example uses values already written in the program.
Output
Code Bhavya
Related exam questions
Related questions in the substring operations category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
March/April 2023 · Q4(b) · 5 marks
Write a C program to insert a substring into a main string from a given position.
Write a function to delete n characters from a given string position.
5 marks
Answer in brief
Substring deletion removes a chosen count of consecutive characters and joins the remaining prefix and suffix.
Algorithm
Find the current string length.
Reject a position beyond the length.
Reject a count greater than length - position.
Move the suffix beginning at position + count to position, including its null terminator.
Worked example
For "Code Bhavya", position 4 identifies the space and count 1 removes it. The suffix Bhavya moves left over that space, followed by its terminator. The result is "CodeBhavya".
Boundary cases
A zero count leaves the text unchanged. Deleting the entire string from position zero produces an empty string. Deleting a suffix leaves a terminator at the deletion start. A start equal to the length is allowed only with a zero count.
Why move the suffix?
A string must remain consecutive from its beginning to its terminator. Simply replacing deleted positions with spaces would change the contents but not perform the requested deletion. Writing a terminator at the start would discard the whole suffix, which is also a different operation.
Overlap and capacity
The move happens inside the existing writable array, and deletion never increases the length. memmove handles the overlapping source and destination. The original argument must already be a valid string; the function does not search beyond arbitrary invalid storage safely.
Complexity
The initial length scan is O(n), and the moved suffix is at most n + 1 bytes. Total time is O(n), with fixed-size explicit counters and no separate result buffer. The operation changes the caller’s original string.
/* CodeBhavya | PPS AR25 | Learning example */
#include <stdio.h>
#include <string.h>
int delete_text(char *s, size_t position, size_t count)
{
size_t length = strlen(s);
if (position > length || count > length - position) { return 0; }
memmove(s + position, s + position + count, length - position - count + 1);
return 1;
}
int main(void)
{
char text[] = "Code Bhavya";
if (!delete_text(text, 4, 1)) { puts("Invalid request"); return 1; }
puts(text);
return 0;
}
Sample input and output
This example uses values already written in the program.
Output
CodeBhavya
Related exam questions
Related questions in the substring operations category from the supplied papers. The marks below are the printed allocations, including any combined subquestion.
March/April 2023 · Q4(b) · 5 marks
Write a C program to insert a substring into a main string from a given position.