118 Intermediate C Programming
The sum of 5 8 11 4 3 27 is 36.
$ ./malloc 7 9 hello 1 6 C 2 4 8
The sum of 7 9 0 1 6 0 2 4 8 is 37.
Here is a review of the relationships between arrays and pointers:
An array always means a pointer. The name of the array is the address of the first
element.
An index ([ and ]) removes one asterisk from the pointer type. If arr’s type is int *,
then arr[3] is int.
A pointer is not necessarily an array. For example,
int * ptr ;1
int a = 5;2
ptr = & a;3
In this case, ptr is a pointer but there is no array. A pointer stores a memory address.
8.3 Functions that Return a Heap Address
A function may return the address of heap memory. For example,
int * f1 ( in t n)1
{2
int * ptr ;3
ptr = malloc ( n * s i z e o f ( in t ) );4
return ptr ;5
}6
void f2 ( void)7
{8
int * arr ;9
arr = f1 (6) ;10
/* return loca t ion */11
arr [4] = 7;12
free ( arr );13
}14
Let’s consider the call stack just before f1 returns ptr:
Symbol Address Value Address Value
ptr 103 10000 10020 ?
value address 102 100 10016 ?
return location 101 line 11 10012 ?
arr 100 ? 10008 ?
10004 ?
10000 ?
(a) Stack Memory (b) Heap Memory
After f1 returns, this is what is in the call stack and heap memory:
Heap Memory 119
Symbol Address Value Address Value
arr 100 10000 10020 ?
10016 ?
10012 ?
10008 ?
10004 ?
10000 ?
(a) Stack Memory (b) Heap Memory
The allocated heap memory is still available because the program has not called free
yet. The stack variable ptr, declared on line 3, is destroyed when f1 returns, because ptr
is on the stack. However, the allocated heap memory is available until it is freed. This is
a fundamental difference between stack and heap memory. Heap memory is more flexible.
The statement,
arr [4] = 872;1
changes an element in the array. Now the stack and heap memory look as follows:
Symbol Address Value Address Value
arr 100 10000 10020 ?
10016 872
10012 ?
10008 ?
10004 ?
10000 ?
(a) Stack Memory (b) Heap Memory
Before f2 finishes, it must call free. Otherwise, the program leaks memory. The pur-
pose of this example is to show that memory allocated by malloc can be passed between
functions. Please be aware that this example does not follow the principle mentioned in
Section 8.1. In this example, malloc and free are called in two different functions. This is
sometimes necessary, but also error-prone. It is easy to forget calling free in f2 because f2
does not call malloc. We have used 10000 as the memory address returned by malloc. In
a real computer, the address can change every time the program runs and the address will
likely be a very large number.
8.4 Two-Dimensional Arrays in C
We have seen two-dimensional arrays already. In Section 6.3, argv is an array of strings.
Each string is an array of characters. Thus, argv is a two-dimensional array. The strings may
have different sizes. The characters in each string are stored contiguously, and the string
pointers are stored contiguously. A C program may create a fixed-size two-dimensional array
in the following way:
int arr2d [8][3];1
// an array with 8 rows and 3 columns2
arr2d [0][2] = 4;3
// assign 4 to the third column of the first row4
120 Intermediate C Programming
arr2d [3][1] = 6;5
// assign 6 to the second column of the fourth row6
In this example, the first dimension has eight rows and the indexes are between zero
and seven (inclusively). The second dimension has three columns; the indexes are between
zero and two. A two-dimensional array is like a matrix.
It is a little more complicated creating a two-dimensional array whose size is known only
at run time by calling malloc. We first create a one-dimensional array of integer pointers
(int *) and then each pointer is used to create an integer array. Fig. 8.1 illustrates this
concept. The first step creates an array of integer pointers. In the second step, each pointer
stores the address of the first element in a one-dimensional integer array. The addresses of
&arr2d[0] and &arr2d[1] are adjacent. However, the values of arr2d[0] (corresponding
to &arr2d[0][0]) and arr2d[1] (corresponding to &arr2d[1][0]) are likely far apart.
arr2d
add2d[0][0]
add2d[0][1]
add2d[0][2]
arr2d[0]
arr2d[1]
arr2d[2]
arr2d[3]
arr2d[4]
arr2d[5]
arr2d[6]
arr2d[7]
add2d[1][0]
add2d[1][1]
add2d[1][2]
add2d[2][0]
add2d[2][1]
add2d[2][2]
add2d[3][0]
add2d[3][1]
add2d[3][2]
add2d[4][0]
add2d[4][1]
add2d[4][2]
add2d[5][0]
add2d[5][1]
add2d[5][2]
add2d[6][0]
add2d[6][1]
add2d[6][2]
add2d[7][0]
add2d[7][1]
add2d[7][2]
FIGURE 8.1: A two-dimensional array has an array of pointers as the first dimension.
Each element points to an array.
An array’s name stores the address of the first element. Therefore, the type of a one-
dimensional array of integers is an integer pointer. If we want to create an array using
malloc, we need to use int *.
int arr [6]; /* an array of fixed size , 6 elemen t s */1
int * arr2 ; /* an integer pointer */2
arr2 = malloc (9 * s i z e o f ( in t ) ); /* 9 e lements */3
arr2 [4] = 19; /* arr2 [4] is an integer */4
free ( arr2 ) ;5
Imagine a new type called one d array. A two-dimensional array would be an array of
one d array. To create this two-dimensional array, malloc is used:
one_d_ array * arr2d ;1
arr2d = malloc ( numrow * s i z e o f ( one _d_array ) ) ;2
The one-dimensional array is itself a pointer to integer; thus, one d array should be
replaced by int *. Consequently, the type of arr2d is int * *. That means that the arr2d
is pointing to int *, and indeed, the first element of arr2d has type int *.
Heap Memory 121
int * * arr2d ;1
arr2d = malloc ( numrow * s i z e o f ( i nt *) );2
This only allocates enough space for the pointers: arr2d[i] is a pointer to an integer.
There is no space for the integers yet. It is necessary to allocate the memory for the integers
separately:
for ( row = 0; row < NUMROW ; row ++)3
{4
arr2d [ row ] = malloc ( NUMCO LUMN * s i z e o f ( in t ) );5
}6
These arrays must be freed later in the program.
for ( row = 0; row < NUMROW ; row ++)7
{8
free ( arr2d [ row ]) ;9
}10
free ( arr2d ); // must be after free ( arr2d [ row ])11
If we freed arr2d before freeing the individual rows, then attempting to free the rows
would be an error. Thus, malloc and free are always in the reverse order: malloc must
be followed by free, and the memory must not be accessed after a call to free.
This is the code implementing this concept.
/* twod array . c1
purpose : show how to create a two - dim ensional array2
The size of the array is 8 rows x 3 columns3
*/4
#in clude < stdio .h >5
#in clude < stdlib .h >6
#d ef in e NUMROW 87
#d ef in e NUMCOLUM N 38
int main ( i n t argc , char * argv [])9
{10
int * * arr2d ;11
int row ;12
/* step 1: create an array of integer pointers */13
arr2d = malloc ( NUMROW * s i z e o f ( i nt *) );14
for ( row = 0; row < NUMROW ; row ++)15
{16
/* step 2: for each row ( i.e ., integer pointer ) ,17
create an integer array */18
arr2d [ row ] = malloc ( NUMCO LUMN * s i z e o f ( in t ) );19
}20
/* now , the two - dimen sional array can be used */21
arr2d [4][1] = 6;22
arr2d [6][0] = 19;23
/* the first index can be 0 to 7 ( i nclusive ) */24
/* the second index can be 0 to 2 ( i nclusive ) */25
26
/* memory must be rele as ed in the rever s e order */27
for ( row = 0; row < NUMROW ; row ++)28
{29
122 Intermediate C Programming
/* release the memory for each row first */30
free ( arr2d [ row ]) ;31
}32
/* now release the array of integer pointers */33
free ( arr2 );34
return EXIT _SUCCES S ;35
}36
After creating the two-dimensional array, it can be used in the same way as a fixed-size
array. Before the program ends, the allocated memory must be released. Memory must be
released in the reverse order that it was allocated. Please be careful about the types used
in creating arrays.
8.5 Pointers and Arguments
A function argument can be a pointer that stores the address in either stack memory
or heap memory. The following example passes an array allocated on the heap memory to
a function:
// argumen t . c1
// pass the address of heap memory as a f un ction argume n t2
3
#in clude < stdio .h >4
#in clude < stdlib .h >5
int sum ( i nt * array , in t length )6
{7
int iter ;8
int answer = 0;9
for ( iter = 0; iter < length ; iter ++)10
{11
answer += array [ iter ];12
}13
return answer ;14
}15
int main ( i n t argc , char * argv [])16
{17
int * arr ;18
int iter ;19
int length = 12;20
int total ;21
arr = malloc ( length * s i z e o f ( i n t ) );22
i f ( arr == NULL )23
{24
printf (" malloc fails . n") ;25
return EXIT _FAILUR E ;26
}27
for ( iter = 0; iter < length ; iter ++)28
{29
arr [ iter ] = iter ;30
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset