0% found this document useful (0 votes)
37 views41 pages

Arrays PT Rs

The document discusses arrays and pointers in C. It begins by defining and initializing a one-dimensional integer array, and accessing its elements. It then covers the sizeof operator, two-dimensional and three-dimensional arrays, and comparing the address and value of variables and array elements. The document also discusses pointers, pointer arithmetic, passing arrays to functions, dynamic memory allocation using malloc and free, and the differences between arrays and pointers.

Uploaded by

Vikash Kathirvel
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)
37 views41 pages

Arrays PT Rs

The document discusses arrays and pointers in C. It begins by defining and initializing a one-dimensional integer array, and accessing its elements. It then covers the sizeof operator, two-dimensional and three-dimensional arrays, and comparing the address and value of variables and array elements. The document also discusses pointers, pointer arithmetic, passing arrays to functions, dynamic memory allocation using malloc and free, and the differences between arrays and pointers.

Uploaded by

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

Arrays and Pointers

R. Inkulu
http://www.iitg.ac.in/rinkulu/

(Arrays and Pointers)

1 / 41

Motivation with Example usage

int func(void) {
int states[5], i; //defining
for (i=0; i<5; i++)
states[i]=i; //initializing
for (i=0; i<5; i++)
printf("%d", states[i]); //accessing the value
return 0;
}
array is used in storing multiple objects of same type
objects in the array are indexed starting from 0
array scope is limited to the function in which it is defined

(Arrays and Pointers)

2 / 41

sizeof() operator

int func(void) {
int a[5];
printf("%d, %d, %d",
sizeof(int), sizeof(a[3]), sizeof(a));
//outputs 4, 4, 20
}
sizeof(object or type name) is a compile-time unary operator to get

size of an object or a type in number of bytes

(Arrays and Pointers)

3 / 41

Two-dimensional arrays
int func(void) {
int a[2][3], i, j;

//defining

for (i=0; i<2; i++)


for (j=0; j<3; j++)
a[i][j] = i+j; //initializing
for (i=0; i<2; i++)
for (j=0; j<3; j++)
printf("%d, ", a[i][j]);

//accessing the value

printf("%d, %d, %d", sizeof(a),


sizeof(a[1]), sizeof(a[1][2]));
//prints 24, 12, 4
return 0;
}
(Arrays and Pointers)

4 / 41

Three-dimensional arrays
int func(void) {
int a[2][3][4], i, j, k;

//defining

for (i=0; i<2; i++)


for (j=0; j<3; j++)
for (k=0; k<4; k++)
a[i][j][k] = i+j; //initializing
for (i=0; i<2; i++)
for (j=0; j<3; j++)
for (k=0; k<4; k++)
printf("%d, ", a[i][j][k]); //accessing
printf("%d, %d, %d, %d", sizeof(a), sizeof(a[1]),
sizeof(a[0][2]), sizeof(a[1][0][2]));
//prints ?
return 0;
}
(Arrays and Pointers)

5 / 41

Address vs Value

int a, b[2];
a = 10;
printf("%d, %p", a, &a);
//prints 10, 0xbfeac818
b[0] = 22; b[1] = 24;
printf("%d, %p, %d, %p", b[0], &b[0], b[1], &b[1]);
//prints 22, 0xbfeac820, 24, 0xbfeac824
memory for arrays is allocated contiguously

(Arrays and Pointers)

6 / 41

Arrays are stored in row-major order

int c[2][3], i, j;
for (i=0; i<2; i++)
for (j=0; j<3; j++) {
printf("%p, ", &c[i][j]);
}
//prints 0xbfd8f650, 0xbfd8f654, 0xbfd8f658,
//0xbfd8f65c, 0xbfd8f660, 0xbfd8f664,
contiguous memory is allocated for the first row, immediately

thereafter for the second row, etc.,

(Arrays and Pointers)

7 / 41

Arrays are stored in row-major order (cont)

int a[2][5][3], i, j, k;
for (i=0; i<2; i++)
for (j=0; j<5; j++)
for (k=0; k<3; k++)
printf("%p, ", &a[i][j][k]);
//observed: difference between any two successive
//addresses printed is four

(Arrays and Pointers)

8 / 41

Initializing arrays while defining

int a[2][5] = {
{0, 11, 22, 33, 44},
{1, 12, 23, 34, 45}
};
for (int i=0; i<2; i++)
for (int j=0; j<5; j++)
printf("%d, ", a[i][j]);
//prints 0, 11, 22, 33, 44, 1, 12, 23, 34, 45,

(Arrays and Pointers)

9 / 41

Introducing pointers
int x = 1, y = 2, z[2];
int *p = NULL;
//p is a pointer to int, initialized with NULL
p = &x;
y = *p;
*p = 0;
p = &z[1];
*p = 5;
*p = *p + 5;

//p points to x
//y is 1
//x is now 0
//p points to z[1]
//z[1] is 5
//z[1] is 10

pointer is jut a variable that saves the address of a memory

location that contains a specific type


when p points to a typeA, p is termed as a pointer to typeA
dereferencing pointer p is denoted with p
(Arrays and Pointers)

10 / 41

Incrementing a pointer
p

z[0]

z[1]

z[2]

z[3]

int z[4];
int *p = &z[0];
*(p+1) = 7;
p += 2;
*p = 5;
*p = *p + 3;
*p += 2;
++(*p);
int *q = p;
*q = 89;

z[0]

z[1]

z[2]

z[3]

//*(p+(1*sizeof(int))) = 7
//i.e., z[1] has 7
//p = p + (2*sizeof(int))
//z[2] has 5
//z[2] has 8
//z[2] has 10
//z[2] has 11
//q also points to z[2]
//z[2] has 89

when p is a pointer to typeA, expression p + i increments p by

i sizeof (typeA)

(Arrays and Pointers)

11 / 41

Ways to access an array


z+0
&z[0]
z[0]

z+2
&z[2]
z[1]
&z[1]
z+1

z[2]

p[0]
p[1]
*(p+0) *(p+1)

z[3]

p+0

&z[3]
z+3

p[2]
*(p+2)

p[3]
*(p+3)

&p[0]

p+1

&p[2]

&p[1]

p+2
&p[3]

p+3

double z[4], *p = z;
...
z[3] = 10;
...
ex. compiler replaces z[i] with (z + (i sizeof (double)))

same is true in case of multi-dimensional arrays


(Arrays and Pointers)

12 / 41

Array name is a pointer


float z[4];
printf("%d, %d, %d", sizeof(p),
sizeof(float), sizeof(*p)); //prints 4, 4, 4
printf("%p, %p, ", z, &z[0]);
//identical values are printed
printf("%p, %p, ", z+1, &z[0]+1);
//identical values (&z[1]) are printed
name of an array (z) is a synonym for the address of z[0];

further, &z[i] + j denotes the address of z[i + j]


however, statements like z = p and z++ are illegal as z is not a

variable
(Arrays and Pointers)

13 / 41

Array name is a pointer (cont)

float z[4];
float *p = &z[0], *q;
q = z;
printf("%p, %p, %p", z, p, q);
//identical values are printed
*(z+2) = 20;
q[3] = 52;
*(q+3) = 58;

(Arrays and Pointers)

//z[2] has 20
//z[3] has 52
//z[3] has 58

14 / 41

More on row-major order of arrays


z[0]
z[1]
z[2]
z[0], z[1], z[2] shown in figure do not occupy additional space

int z[3][4], i, j;
printf("%p, %p, %p, ", z[0], z[1], z[2]);
//prints addresses of three rows i.e, &z[i][0]
printf("%p, %p", &z[2]+1, &z[1]+2);
//prints identical values
printf("%p, %p", z[2]+1, &z[2][1]);
//prints identical values
two-dimensional array is an array of rows:

z[i] is the name of the array that comprises the ith row;
and, &z[i] is the address of the first row
(Arrays and Pointers)

15 / 41

Passing arguments to functions (review)


void func(int y) {
//y has 10
y = 15;
//y has 15
return;
}
int main(void) {
int x=10;
func(x);
printf("%d", x);
return 0;
}

//prints 10 !

function parameters are passed by value

(Arrays and Pointers)

16 / 41

Simulating pass by reference with pass by value

void func(int *y) {


//now the value of y is the address of x
//(x is a variable defined in main)
*y = 15;
}
int main(void) {
int x=10;
func(&x);
printf("%d", x);
}

(Arrays and Pointers)

//address of x is passed to func


//prints 15

17 / 41

Passing arguments to functions: swap func

void swap(int v, int w) {


int tmp = v;
v = w;
w = tmp;
}
int main(void) {
int x=10, y=15;
swap(x, y);
printf("%d, %d", x, y);
}

(Arrays and Pointers)

//prints 10, 15

18 / 41

Simulating pass by reference with pass by value:


swap func

void swap(int *v, int *w) {


int tmp = *v;
*v = *w;
*w = tmp;
}
int main(void) {
int x=10, y=15;
swap(&x, &y);
printf("%d, %d", x, y);
}

(Arrays and Pointers)

//prints 15, 10

19 / 41

Passing one-dimensional arrays to functions


int countNonZeros(int v[], int len) {
//v is a pointer to array x (defined in main), and
//len has 3
int count = 0, i;
for (i=0; i<len; i++)
if (v[i] != 0)
++count;
return count;
}
int main(void) {
int x[3] = {20, 30, 0};
int k = countNonZeros(x, 3);
printf("%d", k);
//prints 2
}
change of values of any element of v in countNonZeros gets reflects

in array x of main
(Arrays and Pointers)

20 / 41

Passing one-dimensional arrays to functions: an


alternative
int countNonZeros(int *v, int len) {
//v has &x[0], and len has 3
int count = 0, i;
for (i=0; i<len; i++)
if (v[i] != 0)
++count;
return count;
}
int main(void) {
int x[3] = {20, 30, 0};
int k = countNonZeros(x, 3);
printf("%d", k);
//prints 2
}
change of values of any element of v in countNonZeros gets reflects

in array x of main
(Arrays and Pointers)

21 / 41

Passing partial arrays to functions


int countNonZeros(int *v, int len) {
//v has &x[1], and len has 2
int count = 0, i;
for (i=0; i<len; i++)
if (v[i] != 0)
//equivalently,
++count;
return count;
}

if (*(v+i) != 0)

int main(void) {
int x[3] = {20, 30, 0};
int k = countNonZeros(&x[1], 2);
printf("%d", k);
//prints 1
}

(Arrays and Pointers)

22 / 41

Passing two-dimensional arrays to functions


void func(double b[][4], int numRows, int numCols)
//equivalently, formal parameter can be b[3][4]
{
...
b[2][3] = 78;
//lvalue is (&b[0][0]+(2*4+2)*sizeof(double))
... }
int main(void) {
double a[3][4];
func(a, 3, 4);
return 0; }
formal parameter need to include the number of columns; the

number of rows are irrelevant: since what is passed is, a pointer to


an array of rows, where each row is an array of [4] integers (ex. to
access a particular element, compiler need to be able to calculate
the offset from the beginning of array b)
(Arrays and Pointers)

23 / 41

Passing multi-dimensional arrays to functions:


an alternative

Homework!

(Arrays and Pointers)

24 / 41

Dynamic Memory
p

double *p = (double *) malloc(count*sizeof(double));


//allocates count*sizeof(double) bytes contiguously;
//p has the address of first byte of those allocated
int i;
for (i=0; i<count; i++) {
p[i] = i*10;
printf("%lf, ", p[i]);
}
//prints 0.000000, 10.000000, 20.000000, 30.000000,
free(p);
//frees contigous memory referred by p
useful when the number of objects to be allocated is not known at

compile-time
system maintains a table of dynamically allocated memory blocks

and their corresp. address ranges


(Arrays and Pointers)

25 / 41

Dynamic vs non-dynamic memory allocation


z

z[0]

z[1]

z[2]

z[3]

double z[4]; //z is from stack


double *p = (double*) malloc(count*sizeof(double));
//p is from stack, and memory block is from heap
...
free(p);
memory for auto variables (including arrays) comes from stack,

whereas the dynamic memory comes from heap


of the process address space
(Arrays and Pointers)

26 / 41

Pointer arithmatic
at (1):
z[0]

double *p = (double*)
malloc(count*sizeof(double));
double *q = NULL;
... //denotes irrelevant
//stmts
//im here (1)
p += 2;
...
q = p;
p
//im here (2)
...
free(p);

z[1]

z[2]

z[3]

NULL
q

at (2):

z[0]

z[1]

z[2]

z[3]

pointer arithmatic is same whether the memory referred by a

pointer is either from the stack or heap


(Arrays and Pointers)

27 / 41

malloc and free pairs


double *p=NULL; int *q = NULL;
...
p = (double*) malloc(countA*sizeof(double));
...
q = (int*) malloc(countB*sizeof(int));
...
free(p);
...
free(q);
in any program, malloc and free must exist as pairs
avoiding free call corresp. to any malloc call causes memory leak
malloc and free corresp. to a block of memory
not necessarily be invoked in the same function
not necessarily bracketed
(Arrays and Pointers)

28 / 41

Dynamic memory: advantages and


disadvantages
advantages:
useful when the number of objects to be allocated is not known at

compile-time
gives flexibility to allocate and deallocate memory based on the

need; careful user of this primitive can extract benefits


disadvantages:
slow due to free/allocated heap space maintainance involved
together with the defragmentation overhead
due to intermittent mallocs and frees
forgetting to deallocate memory causes memory leak

(Arrays and Pointers)

29 / 41

Non-dynamic memory: advantages and


disadvantages

advantages:
compiler will deallocate the memory automatically for all the

global, static, and local memory that it allocated: no memory leak


hassles
disadvantages:
Memory allocation and deallocation are not in the control of user

(Arrays and Pointers)

30 / 41

Avoid dangling pointers after freeing


at (1):
p

...
double *p = (double*)
malloc(count*sizeof(double));
at (2):
...
p
//im here (1)
free(p);
...
dangling
//im here (2)
at (3):
p = NULL;
p
//im here (3)
NULL
...
avoid dangling pointers by resetting pointer variable value after

the free
(Arrays and Pointers)

31 / 41

Returning pointers from functions


double *func(int count) {
double *p = NULL;
...
p = (double*) malloc(count*sizeof(double));
...
return p; }
void func1(int countA) {
int count; double *q = NULL;
...
q = func(count);
...
free(q);
//freeing heap memory allocated in func
...
return; }
heap memory referred by a pointer may require to be freed by the

caller (precise protocol need to be defined)


does not make sense to return the address of a local variable (ex.
array) from a function
(Arrays and Pointers)

32 / 41

Returning pointers from functions (cont)

void *malloc(size_t sizeInBytes) {


...
}
void func() returns nothing

whereas void* func() returns pointer to a block of memory (could


be NULL too) that can contain objects of any type

(Arrays and Pointers)

33 / 41

Few useful dynamic memory related functions


from stdlib.h
void *malloc(size t numBytes)
void free(void *p)
void *calloc(size t numObj, size t sizeOfAObject)
same as malloc but zeros the memory allocated

void *realloc(void *oldMem, size t numBytes)


resizes and where necessary relocates the block pointed by p; moves the
contents of *p to the new location; frees the old memory

void *memcpy(void *to, void *from, int numBytes);


cannot handle the overlap

void *memmove(void *to, void *from, int numBytes);


same as memcpy but handles the overlap

(Arrays and Pointers)

34 / 41

Array of pointers to varying sized arrays


*(buf[0]+2) a.k.a. buf[0][2]

buf
buf[0]
buf[1]
STACK

HEAP

double *buf[2];
buf[0] = (double*) malloc(countA*sizeof(double));
buf[1] = (double*) malloc(countB*sizeof(double));
printf("%d, %d ", sizeof(buf[0]), sizeof(buf));
//prints sizeof(ptr), 2*sizeof(ptr)
...
free(buf[1]);
free(buf[0]);
buf is an array[2] of pointers, each entry of which points to a block

of memory that contains objects of type double


(Arrays and Pointers)

35 / 41

Array of pointers to varying sized arrays (cont)


z

buf
buf[0]
buf[1]

STACK

STACK
*(buf[0]+2) or *(buf[1])

double z[4];
double *buf[2];
buf[0] = &z[0];
buf[1] = &z[2];
printf("%d, %d ", sizeof(buf[0]), sizeof(buf));
//prints 4, 8
...
//no need of free calls

(Arrays and Pointers)

36 / 41

Array of pointers to fixed size arrays


buf

*(buf+2)

*(buf+0)
*(buf+1)

STACK

(*(buf+1))[1]

HEAP

double (*buf)[2] =
(double (*)[2])malloc(count*sizeof(double [2]));
printf("%d, %d, %d, %d",
sizeof(double), sizeof(buf[0]),
sizeof(buf[2]), sizeof(buf));
//prints 8, 16, 16, 4 when count is 3
...
free(buf);
buf points to count number of array[2]s of doubles

in other words, buf[0] is the zeroth arry[2]; buf[1] is the first


array[2]; etc.,
(Arrays and Pointers)

37 / 41

Passing two-dimensional arrays to functions: an


alternative
void func(double (*b)[4])
//b points to contiguous sequence of double [4]s
{
...
}
int main(void) {
double a[3][4];
func(a);
}

//a is an array[3] of array[4]s

as mentioned in the past, formal parameter must include the

number of columns; number of rows are irrelevant

(Arrays and Pointers)

38 / 41

Passing multi-dimensional arrays to functions:


an alternative

Homework!

(Arrays and Pointers)

39 / 41

Memory layouts of various declarations (review)


(i) double a[2];
double *p = &a[0];
(ii) double *p = (double *) malloc(count*sizeof(double));
(iii) double a[2][3];
(iv) double *a[2];
a[0] = (double *) malloc(countA*sizeof(double));
a[1] = (double *) malloc(countB*sizeof(double));
(v) double *a[2], b[2][3];
a[1] = b[0];
(vi) double (*b)[2];
b = (double (*)[2]) malloc(count*sizeof(double [2]));
(vii) double (*b)[2], c[4][2];
b = c;
homework: using these notions, engineer few more declarations
(Arrays and Pointers)

40 / 41

to be continued ...

(Arrays and Pointers)

41 / 41

You might also like