Arrays and Strings in C
VT
U
AD
Module - 3
D
A
What is an Array?
An array is a collection of variables of the same type stored in contiguous
(continuous) memory locations.
Each element in an array is accessed using an index number.
VT
U
AD
Example:
D
A
int marks[5]; // an integer array with 5 elements
Here, elements are: marks[0], marks[1], marks[2], marks[3], marks[4]
Key Points About Arrays
• The first element index = 0
VT
• The last element index = size - 1
U
AD
• All elements are stored next to each other in memory.
D
A
• No automatic bounds checking → Programmer must avoid
accessing beyond array limits.
Declaring and Accessing Arrays
Syntax:
type array_name[size];
VT
U
Example:
AD
D
double balance[100]; // 100 elements of type double
A
balance[3] = 12.23; // stores 12.23 in the 4th element
Example Program: Loading and Printing an Array:
#include <stdio.h>
int main() Output: 0 1 2 3 … 99
{
int x[100];
int t;
VT
// Store values 0 to 99
for(t = 0; t < 100; t++)
U
AD
x[t] = t;
D
// Display values
A
for(t = 0; t < 100; t++)
printf("%d ", x[t]);
return 0;
}
Array Memory Size Formula
Total bytes = sizeof(base type) × length of array
VT
Example:
U
AD
D
int num[10]; → 4 × 10 = 40 bytes (if int = 4 bytes)
A
Arrays and Pointers Relationship
The array name represents the address of its first element.
Example:
VT
int sample[10];
U
AD
int *p;
D
A
p = sample; // same as p = &sample[0];
sample and &sample[0] both mean address of first element.
Passing Arrays to Functions
In C, you cannot pass an entire array, but you can pass a pointer to the first
element.
Example:
void func1(int x[]); // function declaration
int main() {
VT
int i[10];
U
AD
func1(i); // passes address of first element
}
D
A
You can declare the function in 3 ways (all are same to the compiler):
void func1(int *x); // pointer form
void func1(int x[10]); // sized array form
void func1(int x[]); // unsized array form
Strings in C
A string is a null-terminated character array (ends with '\0').
It stores characters contiguously in memory.
VT
Example:
U
AD
char name[6] = "Hello"; // actually stored as: H e l l o \0
D
A
Always make the array 1 character longer than the string length (to
hold '\0').
String Declaration Example
char str[11]; // can hold 10 characters + 1 null character
Common String Functions (from <string.h>)
Function Description Example
strcpy(s1, s2) Copies s2 into s1 strcpy(a, b);
VT
strcat(s1, s2) Appends s2 to s1 strcat(a, b);
U
AD
strlen(s1) Returns length of s1 len = strlen(a);
D
strcmp(s1, s2) Compares two strings (0 if equal) strcmp(a, b)
A
Finds first occurrence of a
strchr(s1, ch) strchr(a, 'e');
character
Finds first occurrence of one string
strstr(s1, s2) strstr(a, "hi");
in another
Example Program Using String Functions
#include <stdio.h>
#include <string.h>
int main()
{
char s1[80], s2[80];
scanf("%s",s1
scanf("%s",s2);
printf("lengths: %d %d\n", strlen(s1), strlen(s2));
if(!strcmp(s1, s2))
VT
printf("The strings are equal\n");
strcat(s1, s2);
U
printf("%s\n", s1);
AD
OUTPUT:
strcpy(s1, "This is a test.\n");
D
printf("%s", s1);
A
hello
if(strchr("hello", 'e')) hello
printf("e is in hello\n"); lengths: 5 5
The strings are equal
if(strstr("hi there", "hi")) hellohello
printf("found hi"); This is a test.
e is in hello
return 0; found hi
}
A
D
AD
U
VT
Pointers in C
VT
U
AD
Module -3
D
A
What is a Pointer?
• A pointer is a variable that stores the memory
address of another variable.
VT
• Example:
U
AD
If variable x is stored at memory address 2000, then a
D
pointer can store 2000.
A
• Pointers point to other variables.
Why Are Pointers Important?
Pointers are a very powerful feature in C because:
1. Functions can modify actual variables by passing their addresses.
2. Dynamic memory allocation (malloc, calloc, free) uses pointers.
3. Faster programs — pointers improve performance for some tasks.
VT
4. Dynamic data structures such as:
U
• Linked lists
AD
• Trees
D
• Graphs
A
• Stacks & Queues
But pointers can also be dangerous:
Using an invalid pointer may crash the program.
Pointer bugs are difficult to find.
Pointer Declaration
To declare a pointer, write:
type *name;
VT
Examples:
int *p; // pointer to an integer
U
AD
float *q; // pointer to a float
char *ch; // pointer to a char
D
A
The base type (int, float, char) tells the compiler what type of data the pointer points
to.
Important:
A pointer “thinks” it points to that type even if memory contains something else.
So always match pointer type with variable type.
Pointer Operators
1) Address-of operator (&) 2) Dereference operator (*)
Returns the address of a variable.
Example: Returns the value stored at an address.
If:
int count = 100;
VT
m = &count; // m contains address of count
U
m = &count; q = *m; // q receives value at
AD
Meaning: address m
D
A
“m receives the address of count.” Then q = 100 (value of count).
If count is stored at 2000, *m means “value stored at address m”.
then m = 2000.
Pointer Expressions
Pointer expressions follow the same basic rules as all other expressions
in C, but there are a few special behaviors that apply only to pointers.
These behaviors are mainly related to:
VT
• Pointer assignment
U
AD
• Pointer conversions
D
• Pointer arithmetic
A
1. Pointer Assignments
You can assign one pointer to another if they are of the same type:
Example:
int x = 99;
VT
int *p1, *p2;
U
AD
p1 = &x; // p1 points to x
D
p2 = p1; // p2 points to same x
A
Both p1 and p2 point to the same memory location.
Output:
Values at p1 and p2: 99 99
Addresses pointed by p1 and p2: same address
To print addresses, use %p in printf().
[Link] Conversions
Pointer conversion means changing one type of
pointer into another type.
VT
Some conversions are safe, and some can cause serious
U
errors.
AD
D
There are two main categories:
A
• Conversions involving void*
• Conversions involving other pointer types
1. Converting to/from void* (Generic Pointer)
Allowed without cast
A void * pointer is called a generic pointer because it can hold the address of any type.
You can assign:
•Any pointer → void *
•void * → Any pointer
without using a cast.
VT
Example:
U
int a = 10;
AD
void *vp;
D
A
vp = &a; // OK
Why is void* used?
•When the data type is unknown
•In functions like malloc(), which return raw memory
•For writing general-purpose functions
2. Conversions Between Other Pointer Types
Any pointer conversion not involving void* must use an explicit cast:
Example:
double x = 100.1;
int *p;
p = (int*) &x; // Cast required
VT
U
AD
Even though this compiles, it is dangerous and may not work correctly.
D
A
Example of Incorrect Pointer Conversion Why does it fail?
•int = 4 bytes
double x = 100.1, y; •double = 8 bytes
When dereferencing:
int *p; *p → reads only 4 bytes from the 8-
p = (int*) &x; // p now points to a double, but thinks it points to an int byte double
So the value stored in y is garbage,
y = *p; // WRONG! Only 4 bytes read (int), not 8 bytes (double) not 100.1.
#include <stdio.h>
int main(void)
{ Key Rule
Pointer operations depend on the pointer’s
double x = 100.1, y; declared base type — not on the actual data.
int *p; Even if a pointer points to a different type of data,
it will still behave according to its own declared
/* The next statement causes p (which is an
VT
type.
integer pointer) to point to a double. */ Example:
U
An int* will always behave like it points to an int
AD
p = (int *) &x; — it reads/writes 4 bytes only.
D
/* The next statement does not operate as expected. */
A
y = *p;
/* attempt to assign y the value x through p */
/* The following statement won't output 100.1. */
printf(''The (incorrect) value of x is: %f", y);
return 0
}
One other pointer conversion is allowed:
Integer Pointer Conversions
You can convert:
•an integer → pointer
•a pointer → integer
But:
VT
•Must use an explicit cast
U
•Result is implementation-defined
AD
•May cause undefined behavior
D
Example:
A
long int addr = 2000;
int *p = (int*) addr; // dangerous
Exception:
Converting 0 to a pointer does not need a cast.
int *p = 0; // NULL pointer
3. Pointer Arithmetic (Addition & Subtraction
Only)
• C allows ONLY two arithmetic operations on pointers:
VT
U
• Addition (+)
AD
D
•
A
Subtraction (−)
• Other operations like *, /, %, <<, >>, etc. are NOT allowed.
How Pointer Arithmetic Works
Pointer arithmetic is based on the size of the data type the pointer points to.
Example:
Let:
int *p1 = (int*) 2000;
VT
Assume:
U
sizeof(int) = 2 bytes
AD
Then:
D
p1++
A
Moves pointer to the next integer location.
General Rule
2000 → 2002 Whenever you increment or decrement a
pointer:
p1-- pointer ± 1 = pointer ± (size of
Moves pointer backwards: base type)
2000 → 1998
Char Pointers Work Differently
Since char is always 1 byte, pointer arithmetic looks "normal":
ch = (char*) 3000;
ch+1 = 3001
VT
ch+2 = 3002
U
AD
...
D
A
Adding/Subtracting an Integer to a Pointer
You can move a pointer forward/backward by N elements:
Example:
p1 = p1 + 12;
VT
This moves p1 forward by 12 integers, not 12 bytes.
U
AD
If int = 2 bytes:
D
p1 = p1 + 12 → moves 24 bytes
A
Subtracting One Pointer from Another
You CAN subtract two pointers, provided they point into the same array.
This gives the number of elements between them, not bytes.
Example:
VT
int arr[10];
int *p = &arr[2];
U
int *q = &arr[7];
AD
D
int diff = q - p; // diff = 5 (elements apart)
A
NOT Allowed in Pointer Arithmetic
You cannot:
•Add two pointers
•Multiply or divide pointers
•Add floats/doubles to pointers
•Use bitwise operators on pointers
Pointer Comparison
You can compare two pointers using:
< > <= >= == !=
VT
U
Example:
AD
D
if(p < q)
A
printf("p points to lower memory\n");
Comparisons only make sense when:
Both pointers point into the same array or memory block.
A
D
AD
U
VT
Pointers and Arrays
VT
U
AD
Module-3
D
A
Pointer & Array Relationship
• In C, array name itself acts like a pointer (a constant pointer).
• Example:
VT
• char str[80], *p1;
U
AD
• p1 = str;
D
A
• str → address of the first element
• So p1 = str; means
p1 now points to str[0]
Why two methods?
Accessing Array Elements •Array indexing → easy to read.
•Pointer arithmetic → faster in many cases.
That's why professional C programmers often prefer
pointer method.
You can access array elements in two ways:
Using array indexing:
VT
str[4];
U
This gives the 5th element (because index starts from 0).
AD
D
Using pointer arithmetic:
A
*(p1 + 4);
Since p1 points to the first element, p1 + 4 moves 4 positions forward.
Both expressions return the same character.
Example Program: Accessing Array Elements Using Pointer & Array Index:
#include <stdio.h>
int main()
{
char str[] = "HELLO"; // an array of characters Using Array Indexing:
char *p = str; // pointer points to first element str[0] = H
str[1] = E
printf("Using Array Indexing:\n"); str[2] = L
str[3] = L
VT
for (int i = 0; str[i] != '\0'; i++)
str[4] = O
{
U
printf("str[%d] = %c\n", i, str[i]);
AD
Using Pointer Arithmetic:
} *(p + 0) = H
D
*(p + 1) = E
A
printf("\nUsing Pointer Arithmetic:\n"); *(p + 2) = L
for (int i = 0; *(p + i) != '\0'; i++) *(p + 3) = L
{ *(p + 4) = O
printf("*(p + %d) = %c\n", i, *(p + i));
}
return 0;
}
Arrays of Pointers
What is an Array of Pointers?
Just like we can have:
•array of int
•array of char
•array of float
VT
U
We can also have: This means:
AD
•x is an array of 10 elements
array of pointers •Each element is a pointer to int
D
So:
A
x[0] -> pointer to int
Example: x[1] -> pointer to int
int *x[10]; ...
x[9] -> pointer to int
Storing an Address in a Pointer Array
Let’s say we have an integer variable:
int var = 100;
VT
U
Store its address in the 3rd element of array x:
AD
x[2] = &var;
D
A
To get the value of var through the array:
*x[2]; // gives 100
// C program to demonstrate the use of array of pointers
#include <stdio.h>
int main() OUTPUT:
{
// declaring some temp variables Value of var1: 10 Address: 0x7fff1ac82484
int var1 = 10; Value of var2: 20 Address: 0x7fff1ac82488
int var2 = 20; Value of var3: 30 Address: 0x7fff1ac8248c
int var3 = 30;
VT
U
// array of pointers to integers
AD
int* ptr_arr[3] = { &var1, &var2, &var3 };
D
A
// traversing using loop
for (int i = 0; i < 3; i++) {
printf("Value of var%d: %d\tAddress: %p\n", i + 1, *ptr_arr[i], ptr_arr[i]);
}
return 0;
}
A
D
AD
U
VT
Passing an Array of Pointers to a Function
You can pass pointer arrays just like normal arrays:
void display_array(int *q[])
{
VT
int t;
U
AD
for(t=0; t<10; t++)
D
printf("%d ", *q[t]);
A
}
Here:
•q is an array of integer pointers
•*q[t] → value at pointer
Multiple Indirection (Pointer to Pointer)
What is Single Indirection?
A normal pointer stores the address of a variable.
Example:
VT
int x = 10;
U
AD
int *p = &x; // p points to x
D
p → x → value(10)
A
Access value:
*p // gives 10
What is Multiple Indirection? (Pointer to Pointer)
A pointer can store the address of another pointer.
Example:
VT
int a = 10;
U
AD
int *b = &a; // pointer to int
D
A
int **c = &b; // pointer to pointer
Memory chain:
c → b → a → value(10)
#include <stdio.h>
int main()
{
int a = 10;
int *b = &a;
int **c = &b;
VT
printf("Value of a = %d\n", a);
U
printf("Using pointer b : %d\n", *b);
AD
printf("Using pointer c : %d\n", **c);
D
return 0;
A
}
OUTPUT:
Value of a = 10
Using pointer b : 10
Using pointer c : 10
Why is it called “double pointer”?
Because you need two stars () to reach the value**:
Pointers Initialization
What happens when you declare a pointer?
When you declare a local pointer (inside a function) but don’t assign a
VT
value, it contains garbage/unknown value.
U
Using such a pointer may crash the program.
AD
Example:
D
A
int *p; // contains unknown value
*p = 10; // dangerous! may crash
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Null Pointer :
•C programmers set unused pointers to NULL (value 0).
•NULL means “this pointer is not pointing anywhere.”
Ways to assign NULL:
char *p = 0;
VT
p = NULL;
U
NULL does not automatically protect you.
AD
This is wrong:
D
A
int *p = NULL;
*p = 10; // still dangerous → writing to address 0 → crash
NULL is only a convention to show “empty pointer”, NOT a safety
feature.
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
#include <stdio.h>
#include <string.h>
// Function to look up a name in the array
int search(char *p[], char *name);
int search(char *p[], char *name)
char *names[] = {
{
"Herb",
int t;
"Rex",
"Dennis",
// Loop through the list until NULL is found
"John",
for (t = 0; p[t] != NULL; t++)
NULL // NULL marks the end of the list
{
};
VT
// Compare each string with the name being searched
if (strcmp(p[t], name) == 0)
U
int main(void)
return t; // return its index if found
AD
{
}
// Search for "Dennis"
D
if (search(names, "Dennis") != -1)
A
return -1; // return -1 if not found
printf("Dennis is in the list.\n");
}
// Search for "Bill"
if (search(names, "Bill") == -1)
printf("Bill not found.\n");
return 0;
}
A
D
AD
U
VT
Sum of Array Elements using
Pointers
VT
U
AD
Example
D
A
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Stack Program in C (Using Pointers)
• What is a Stack?
• A stack is a list where items go in and come out in a special
way:
VT
• First-In, Last-Out (FILO) or Last-In, First-Out (LIFO)
U
• Like a stack of plates: the last plate kept on top is the first one
AD
removed.
D
A
• What are Push and Pop?
• push(x) → puts a new value on top of the stack
• pop() → removes and returns the top value
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
#include <stdio.h>
if (choice == 1)
#include <stdlib.h>
{
printf("Enter value to push: ");
#define SIZE 5
scanf("%d", &value);
push(value);
int stack[SIZE];
}
int *top;
else if (choice == 2)
{
void push(int value);
printf("Popped value: %d\n", pop());
int pop();
VT
}
else if (choice == 3)
U
int main()
{
AD
{
break;
int choice, value;
}
D
top = stack - 1;
else
A
while (1)
{
{
printf("Invalid choice!\n");
printf("\n--- STACK MENU ---\n");
}
printf("1. Push\n");
}
printf("2. Pop\n");
return 0;
printf("3. Exit\n");
}
printf("Enter your choice: ");
scanf("%d", &choice);
void push(int value) { Push 10 Push 20 Push 30
if (top == stack + SIZE - 1) { Before: Before: top → stack[2]
top → stack[-1] top → stack[0] store 30
printf("Stack Overflow!\n");
return; After top++: After top++:
} top → stack[0] top → stack[1]
top++; Store: Store:
*top = value; stack[0] = 10 stack[1] = 20
printf("%d pushed onto stack.\n", value);
VT
}
U
int pop() {
AD
if (top < stack) { Pop()
D
top → stack[2]
printf("Stack Underflow!\n");
A
(30)
exit(1); return 30
} top-- → stack[1]
(20 becomes new
int value = *top; top)
top--;
return value;
}
A
D
AD
U
VT