0% found this document useful (0 votes)
8 views18 pages

3rd Module Array and Pointers Notes

The document provides a comprehensive overview of arrays in C, including single-dimensional and multi-dimensional arrays, their memory representation, and how to pass them to functions. It also covers string manipulation using character arrays, pointer usage, and variable-length arrays introduced in C99. Key concepts such as indexing, memory allocation, and common functions for string operations are explained with examples.

Uploaded by

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

3rd Module Array and Pointers Notes

The document provides a comprehensive overview of arrays in C, including single-dimensional and multi-dimensional arrays, their memory representation, and how to pass them to functions. It also covers string manipulation using character arrays, pointer usage, and variable-length arrays introduced in C99. Key concepts such as indexing, memory allocation, and common functions for string operations are explained with examples.

Uploaded by

Sahana Sowmya
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Array

An array is a collection of many values of the same data type stored using one single name
A specific element in an array is accessed by an index.

1. In C, all arrays consist of contiguous memory locations.


The lowest address corresponds to the first element and the highest address to the last
element.
2. The most common array is the string, which is simply an array of characters terminated by a
null.

Example: int marks[5];


This means marks can store 5 integers.

Single dimensional Array


General form:
type array_name[size];

Example: double balance[100];

This means balance has 100 values of type double.

Indexing in Arrays
Arrays always start from index 0.
So an array with 10 elements has indices: 0 to 9.
Example:
balance[3] = 12.23;
This means: store 12.23 in the 4th element.

Example Program
int x[100];
int t;
for(t = 0; t < 100; t++)
x[t] = t;
for(t = 0; t < 100; t++)
printf("%d ", x[t]);
Meaning: First loop → stores numbers 0 to 99 in array x.
Second loop → prints all values.

Memory Used by Array


Formula: total bytes = sizeof(data type) × number of elements

Example: int x[10];


If 1 int = 4 bytes, total = 4 × 10 = 40 bytes.
No Bound Checking in C
C does not check if you go out of array limits.
Example:
int count[10];
for(i = 0; i < 100; i++)
count[i] = i;
This is wrong because array size is 10, but loop writes 100 values → memory gets corrupted.

Generating a Pointer to an Array


Arrays are Stored in Continuous Memory
Example: char a[7];
Memory may look like:

Element a[0] a[1] a[2] a[3] a[4] a[5] a[6]


Address 1000 1001 1002 1003 1004 1005 1006

Each goes to the next memory location.

Given:
int sample[10];
We can get pointer to first element:
int *p;
p = sample;
This means p stores the address of sample[0].
sample and &sample[0] are basically the same.

Passing Single Dimensional Arrays to Functions


You CANNOT pass the whole array directly.
But you CAN pass its address, which is done by writing the array name:
For example, to receive i, a function called func1( ) can be declared as
int main(void)
{
int i[10];
func1(i); // passes address of i[0]
/* . . . */
}
If a function receives a pointer to a single-dimension array, you can declare its formal parameter in
one of three ways: as a pointer, as a sized array, or as an unsized array.
Method 1 → Using pointer
void func1(int *x)
Method 2 → Using sized array
void func1(int x[10])
Method 3 → Using unsized array
void func1(int x[]) All three mean the SAME thing.
As you can see, the length of the array doesn't matter as far as the function is concerned because
performs no bounds checking.

Strings
By far the most common use for the one-dimensional array is as a character string.
In C, a string is a null-terminated character array. (A null is zero.)
Thus, a string contains the characters that make up the string followed by a null.
The null-terminated string is the only type of string defined by C.

When declaring a character array that will hold a string, you need to declare it to be one character
longer than the largest string that it will hold. For example, to declare an array str that can hold a 10-
character string, you would write

char str[11];

Specifying 11 for the size makes room for the null at the end of the string.

When you use a quoted string constant in your program, you are also creating a null-terminated
string.
A string constant is a list of characters enclosed in double quotes. For example: ''hello there"

You do not need to add the null to the end of string constants manually— the compiler does this for
you automatically.

C supports a wide range of functions that manipulate strings. The most common are listed here:
Name Function

strcpy(s1, s2) Copies s2 into s1

strcat(s1, s2) Concatenates s2 onto the end of s1

strlen(s1) Returns the length of s1

strcmp(s1, s2) Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if
s1>s2
strchr(s1, ch) Returns a pointer to the first occurrence of ch in s1

strstr(s1, s2) Returns a pointer to the first occurrence of s2 in s1


These functions use the standard header <string.h>. The following program illustrates the use of
these string functions:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s1[80], s2[80];
gets(s1);
gets (s2);
printf("lengths: %d %d\n", strlen(s1), strlen(s2));
if(!strcmp(s1, s2)) printf("The strings are equal\n");
strcat(s1, s2);
printf (''%s\n", s1);
strcpy(s1, "This is a test.\n");
printf(s1);
if(strchr("hello", 'e')) printf("e is in hello\n");
if(strstr("hi there", "hi")) printf("found hi");
return 0;
}

o/p
lengths: 5 5
The strings are equal
hellohello
This is a test.
e is in hello
found hi
If you run this program and enter the strings "hello" and "hello", the output is
Remember, strcmp( ) returns false if the strings are equal. Be sure to use the logical ! operator to
reverse the condition, as just shown, if you are testing for equality.

Two-Dimensional Arrays
A two-dimensional array is an array of arrays. It is used to store data in a table or matrix form — with
rows and columns.

Declaration
A 2D array is declared like this:
int d[10][20];
Here:
10 → number of rows
20 → number of columns
So, it can store 10 × 20 = 200 integer values.

Each element is accessed using two indexes — one for the row and one for the column.
Example:
d[1][2]; // Accesses element in 2nd row, 3rd column
Example Program
#include <stdio.h>
int main(void)
{
int t, i, num[3][4];
for(t=0; t<3; ++t)
for(i=0; i<4; ++i)
num[t][i] = (t*4) + i + 1;
for(t=0; t<3; ++t) {
for(i=0; i<4; ++i)
printf("%3d", num[t][i]);
printf("\n");
}
return 0;
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12

Explanation:
num[0][0] = 1, num[0][1] = 2, num[2][3] = 12
Data is stored row by row in memory.

Memory Representation
In memory, a 2D array is stored row-wise (called row-major order).

For example:
num[0][0], num[0][1], num[0][2], num[0][3],
num[1][0], num[1][1], num[1][2], num[1][3], ...

Formula for memory required:


Bytes = size of 1st index × size of 2nd index × size of (data type)
Example: For int a[10][5] → 10 × 5 × 4 = 200 bytes (since int = 4 bytes)
Passing 2D Array to Function
When a 2D array is passed to a function, the number of columns must be specified, so the compiler
knows the correct memory layout.

Example:
void func1(int x[][10]) {
// Function body
}

Here, the number of columns (10) must be known, but the number of rows can vary.

Figure 4-2
A two-dimensional array

Advantages
[Link] store matrix-like data (tables, marks, grids, etc.)
[Link] code organized and easier to read.
[Link] in programs involving matrices, images, and tables.

Multidimensional Arrays
Definition
A multidimensional array is an array that has more than two dimensions.
It means an array of arrays of arrays.

In simple words,
A 1D array stores data in a line (like a list).
A 2D array stores data in a table (rows & columns).
A 3D or higher array stores data in a cube or multi-layer format

General Form
The general way to declare a multidimensional array is:
type name[Size1][Size2][Size3]...[SizeN];
Example:
int m[4][3][6][5];
Here,
m is a 4-dimensional array
It has 4 blocks, each block has 3 layers, each layer has 6 rows, and each row has 5 columns.

Memory Usage
Memory used = product of all dimensions × size of data type
Example:
If we have a 4D character array:
char arr[10][6][9][4];
Then,
Memory = 10 × 6 × 9 × 4 = 2160 bytes (since 1 character = 1 byte)
If it were an int array (2 bytes per int), memory = 2160 × 2 = 4320 bytes
If it were a double array (8 bytes per double), memory = 2160 × 8 = 17280 bytes
The more dimensions you add, the more memory your program uses.

Accessing Elements
Each element is accessed using multiple indices.
Example:
m[2][1][4][3];
This means:
Block 2
Layer 1
Row 4
Column 3
Access time becomes slower as the number of dimensions increases because the computer must
calculate more index positions.

Passing Multidimensional Arrays to Functions


When passing multidimensional arrays to a function, you must specify all dimensions except the first
one.
int m[4][3][6][5];
To pass this array to a function:
void func1(int d[][3][6][5]) {
/* function code */
}
You can include the first dimension too if you like, but it’s not required.

Important Points
Multidimensional arrays are useful for representing 3D data like images, 3D coordinates, or scientific
data.
They are stored in row-major order (row by row) in memory.
Too many dimensions can make programs slow and memory-heavy.
Character arrays that hold strings allow a shorthand initialization that takes
the form:
char array_name[size] = ''string";
For example, this code fragment initializes str to the phrase "I like C":
char str[9] = "I like C";
This is the same as writing
char str[9] = {'I', ' ', 'l', 'i', 'k', 'e',' ', 'C', '\0’};
Because strings end with a null, you must make sure that the array you declare is long enough to
include the null.
This is why str is nine characters long even though "I like C" is only eight. When you use the string
constant, the compiler automatically supplies the null terminator.

Multidimensional arrays are initialized the same as single-dimension ones. For example, the
following initializes sqrs with the numbers 1 through 10 and their squares.
int sqrs[10] [2] = {
1, 1,
2, 4,
3, 9,
4, 16,
5, 25,
6, 36,
7, 49,
8, 64,
9, 81,
10, 100
};
When initializing a multidimensional array, you may add braces around the initializers for each
dimension. This is called sub aggregate grouping.

For example, here is another way to write the preceding declaration:


int sqrs[10] [2] = {
{1, 1},
{2, 4},
{3, 9},
{4, 16},
{5, 25},
{6, 36},
{7, 49},
{8, 64},
{9, 81},
{10, 100}
};
When using sub aggregate grouping, if you don't supply enough initializers for a given group, the
remaining members will be set to zero, automatically.
Unsized Array Initializations
Imagine that you are using array initialization to build a table of error messages, as shown here:
char e1[12] = "Read error\n";
char e2[13] = ''Write error\n";
char e3[18] = "Cannot open file\n";
As you might guess, it is tedious to count the characters in each message manually to determine the
correct array dimension.

Fortunately, you can let the compiler automatically calculate the dimensions of the arrays. If, in an
array initialization statement, the size of the array is not specified,
the compiler automatically creates an array big enough to hold all the initializers present.

This is called an unsized array. Using this approach, the message table becomes
char e1[] = "Read error\n";
char e2[] = "Write error\n";
char e3[] = "Cannot open file\n";
Given these initializations, this statement
printf("%s has length %d\n", e2, sizeof e2)
will print
Write error
has length 13
Unsized array initializations are not restricted to one-dimensional arrays.

For multidimensional arrays, you must specify all but the leftmost dimension.

(The other dimensions are needed to allow the compiler to index the array properly.)

In this way, you can build tables of varying lengths, and the compiler automatically allocates enough
storage for them.

For example, the declaration of sqrs as an unsized array is shown here:


int sqrs[] [2] = {
{1, 1),
{2, 4},
{3, 9},
{4, 16},
{5, 25},
{6, 36},
{7, 49},
{8, 64},
{9, 81},
{10, 100}
};
The advantage of this declaration over the sized version is that you may lengthen or shorten the
table without changing the array dimensions.
Variable-Length Arrays
As explained earlier, in C89 array dimensions must be declared using constant expressions.
Thus, in C89 the size of an array is fixed at compile time.
However, this is not the case for C99, which adds a powerful new feature to arrays:
variable length.

In C99, you can declare an array whose dimensions are specified by any valid expression, including
those whose value is known only at run time.
This is called a variable-length array.
However, only local arrays (that is, those with block scope or prototype scope) can be of variable
length. Here is an example of a variable-length array:
void f(int dim)
{
char str[dim]; /* a variable-length character array */
/* . . . */
}
Here, the size of str is determined by the value passed to f( ) in dim. Thus, each call to f( ) can result
in str being created with a different length.
One major reason for the addition of variable-length arrays to C99 is to support numeric processing.

Pointer
A pointer is a variable that stores the memory address of another variable.
If a variable count is stored in memory location 1003, then another variable (pointer) can store that
address.
Example : If variable count is stored at address 1003 and has the value 10,then a pointer variable
holds 1003, meaning it points to count.

Diagram: Memory → Variable count → Address 1003 Pointer → Holds address 1003

Meaning: Pointer helps find and use the value stored at another location in memory.

Pointer Variables
A pointer variable must be declared before use
It is declared with a base type and a * symbol.

Syntax: type *name;

Example: int *p;

Here, p is a pointer to an integer variable.

If x = 5, then we can assign its address to the pointer using

p = &x;
Now, p holds the address of x, and *p gives the value 5.

Pointer Operators
To understand the above assignment better, assume that the variable count uses memory location
2000 to store its value. Also assume that count has a value of 100. Then, after the preceding
assignment, m will have the value 2000.

There are two pointer operators in C:

1.& (Address-of operator) → gives the address of a variable.


Example: m = &count;
Now m stores the address of count.
If count is at address 2000, then m = 2000.

2. * (Value-at operator) → gives the value stored at the address.


Example: q = *m;
Here, if m stores address of count, then q gets the value of count.

So, & gives address and * gives value.

Pointer Expressions
In general, expressions involving pointers conform to the same rules as other expressions. This
section examines a few special aspects of pointer expressions, such as assignments, conversions, and
arithmetic.

[Link] Assignment
You can assign one pointer to another if both are of the same type.
Example:
#include <stdio.h>
int main(void)
{
int x = 99;
int *p1, *p2;
p1 = &x;
p2 = p1;
printf("Values at p1 and p2: %d %d\n", *p1, *p2);
printf("Addresses pointed to by p1 and p2: %p %p", p1, p2);
return 0;
}
Output: Values at p1 and p2: 99 99
Addresses pointed to by p1 and p2: same address
Meaning: Both p1 and p2 point to the same variable x.

Pointer Comparisons
Two pointers can be compared using relational operators if they point to the same array or memory
block.
if(p < q)
printf("p points to lower memory than q\n");
This checks which pointer is located first in memory.
Pointer comparison is mainly used with arrays.

Pointer Conversions
C allows converting one type of pointer into another type using type casting.
A special type is void * — called a generic pointer.

Example:
#include <stdio.h>
int main(void)
{
double x = 100.1, y;
int *p;
p = (int )&x; // cast double to int*
y = *p; // incorrect usage
printf("The (incorrect) value of x is: %f", y);
return 0;
}
Here, p is an integer pointer but points to a double. This gives wrong results because pointer
operations depend on the pointer type, not the object type.

Pointer Arithmetic
In C, pointers store the address (memory location) of a variable.
You can do only two arithmetic operations with pointers:

Addition
Subtraction

Example 1: Incrementing a Pointer


Let’s say
int *p1;
and assume p1 currently holds the value 2000 (memory address).
If integers take 2 bytes in memory,Then after this operation:
p1++;
Now p1 will become 2002, not 2001.
Because the pointer moves to the next integer location (2 bytes ahead).

Example 2: Decrementing a Pointer


If you do:
p1--;
Then p1 will move back by 2 bytes, becoming 1998.

General Rule:
When you increment a pointer → it moves to the next element of its type.
When you decrement a pointer → it moves to the previous element.
So:
For int pointer → moves by 2 bytes (if int = 2 bytes)
For char pointer → moves by 1 byte (since char = 1 byte)
For float pointer → moves by 4 bytes (if float = 4 bytes)
Example:p1 = p1 + 12;
This means p1 will move 12 elements forward (not 12 bytes).
If p1 is an int pointer (2 bytes each), it actually moves 24 bytes in memory.

Important Rules:
You cannot:
Add two pointers together
Multiply or divide pointers
Add float/double to a pointer
Use bitwise operators on pointers

You can:
Add or subtract integers to/from pointersSubtract one pointer from another (to find how many
elements apart they are)
example

Figure 5-2
All pointer arithmetic is relative
to its base type (assume 2-byte integers)

Diagram Explanation:
In the image,
char *ch = (char *)3000;
int *i = (int *)3000;

For char, each next address increases by 1 (3000, 3001, 3002, 3003, …).
For int, each next address increases by 2 (3000, 3002, 3004, 3006, …).
This shows how pointer arithmetic depends on the data type.

Relationship between Pointer and Array:


In C, arrays and pointers are closely related.
An array name itself acts like a constant pointer that stores the address of the first element in the
array.
Example: char str[80], *p1;
p1 = str;
Here, p1 points to the first element of the array str.-

Accessing Array Elements:


You can access array elements in two ways:
[Link] array index: str[4];
→ This gives the 5th element (since index starts at 0).

2. Using pointer arithmetic:*(p1 + 4);


→ This also gives the same 5th element.
Both are equivalent, because:
str[i] means *(str + i) The array name str acts like a pointer to its first element

Example Program
Program 1: Using array notation
#include <stdio.h>
void putstr(char s[])
{
int t;
for (t = 0; s[t]; t++)
putchar(s[t]);
}
int main()
{
putstr("Hello World");
return 0;
}
Output:
Hello World

Program 2: Using pointer notation


#include <stdio.h>
void putstr(char *s)
{
while (*s)
putchar(*s++);
}
int main()
{
putstr("Hello World");
return 0;
}

Output:
Hello World

Explanation (same for both)

The function receives a string (like "Hello World").


It prints one character at a time using putchar().
The loop continues until the null terminator '\0' (end of the string).

Both programs give the same output:


Hello World

Arrays of Pointers:
You can also create an array that holds pointers.
Example: int *x[10];
→ x is an array of 10 pointers to integers.
You can assign:
x[2] = &var;
→ This stores the address of variable var in the third pointer.
To get the value of var, use:*x[2];
Arrays of pointers are useful for storing strings or dynamic data.
Example:
static char *err[] = { "Cannot Open File\n", "Read Error\n", "Write Error\n"};
printf("%s", err[1]); // prints "Read Error"

Multiple Indirection
Definition:
Multiple indirection is the process of using more than one level of pointers.
It allows a pointer to point to another pointer, which may again point to another pointer, and so on.
This is useful in applications like dynamic memory allocation, arrays of strings, and working with
complex data structures (linked lists, trees, etc.).

Detailed Example:
#include <stdio.h>
int main()
{
int a = 25;
int *p = &a; // single pointer
int **q = &p; // double pointer
int ***r = &q; // triple pointer
printf("Value of a = %d\n", a);
printf("Value using *p = %d\n", *p);
printf("Value using **q = %d\n", **q);
printf("Value using ***r = %d\n", ***r);
return 0;
}
Output:Value of a = 25
Value using *p = 25
Value using **q = 25
Value using ***r =25

Explanation:
p → points to a
q → points to p
r → points to q
So, ***r finally gives the value of a.

Advantages:
[Link] in handling complex data structures.

2. Useful for passing pointers to functions (e.g., changing pointer values inside a function).
3. Used in dynamic memory allocation (like double pointer for 2D arrays).

Pointer Initialization in C
Definition:
Pointer initialization means assigning a valid address to a pointer at the time of declaration.
If a pointer is used before initialization, it may lead to undefined behavior.

[Link] and Initializing a Pointer:


int a = 20;
int *p = &a; // pointer p initialized with address of variable a

2. Accessing Value and Address:


printf("Address of a = %p\n", &a);
printf("Address stored in p = %p\n", p);
printf("Value of a using pointer = %d\n", *p);

Example Program:
#include <stdio.h>
int main()
{
int a = 25;
int *p = &a; // initialization of pointer
printf("Value of a = %d\n", a);
printf("Address of a = %p\n", &a);
printf("Pointer p holds = %p\n", p);
printf("Value using pointer = %d\n", *p);
return 0;
}
Output: Value of a = 25
Address of a = 0x7ffee9c8
(example)Pointer p holds = 0x7ffee9c8
Value using pointer = 25

Initializing Pointer with NULL:


int *ptr = NULL;
// pointer not pointing to any variable
Used to avoid garbage values.

Safe way to check before accessing pointer:


if(ptr != NULL)
printf("Pointer is initialized");
Advantages of Proper Initialization:

[Link] segmentation faults or runtime errors.

2. Makes the program safe and reliable.

3. Helps to manage dynamic memory correctly.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

You might also like