arrays and pointers lone leth thomsen. march 2006basis-c-5/ll2 what is an array an array is a...
TRANSCRIPT
Arrays and pointers
Lone Leth Thomsen
March 2006 Basis-C-5/LL 2
What is an array
• An array is a consecutive series of variables that share one variable name
• The individual data items in an array must all be of the same data type, accessed using an index
• Often used when dealing with multiple data items possessing common characteristics
• E.g. 24 hourly temperature readings might be stored in array named temperature
March 2006 Basis-C-5/LL 3
What is an array 2
1 3 5 … 9 11 13
0 1 2 … n-3 n-2 n-1
Numbers denoting thearray subscripts or indices
These numbers indicate thevalue stored in array element
March 2006 Basis-C-5/LL 4
Basics about arrays
• An array uses a single identifier, together with an integer index, to create one variable that can hold many values
• An array is created as a normal variable, but with the addition of [ ] indicating the size of the array
• Each value in an array is accessed using the identifier and a valid index in [ ]
• Each value in the array is called an element, and the identifier by itself resolves to the address of where the array is in memory
March 2006 Basis-C-5/LL 5
• An array has a fixed number of elements based on its creation
• The elements are always numbered from 0 to 1 less than the array’s size
• Arrays store many values but have only one identifier
Basics about arrays 2
March 2006 Basis-C-5/LL 6
Basics about arrays 3
• The array identifier represents the memory location of where the array begins
• The array index represents the offset to an area of storage in the array. The offset depends on the array type. For example, an int array in Unix has an offset of 4 bytes
March 2006 Basis-C-5/LL 7
Visual representation
?
?
23
?
int x[4];
x[2]=23;
342901
342905
342909
342913
0
1
2
3
X
AddressOffset
Identifier
Value
March 2006 Basis-C-5/LL 8
A simple example#include <stdio.h>int main(void)
{int i , x[5] , total = 0 ;for ( i = 0 ; i < 5 ; i++ )
{printf( “Enter mark %d” , i );scanf ( “%d” , &x[ i ] );}
for ( i = 0 ; i < 5 ; i++ )total = total + x[i];
printf ( “The average is %d” , total / 5 );return 0;}
March 2006 Basis-C-5/LL 9
The array element operator [ ]
• The array element operator is used to reference a specific array element
• The expression inside the array element must resolve to type int. This value is known as an index
• The value of the index can be any number, but care should be taken that the index falls within the bounds of the array. The bounds of an array are defined as 0 to 1 less than the size of the array
March 2006 Basis-C-5/LL 10
Array example
#include <stdio.h>
int main(void)
{
int x[5];
x[0]=23; /* valid */
x[2.3]=5; /* invalid: index is not an int */
return 0;
}
March 2006 Basis-C-5/LL 11
Initialising arrays
• An array is initialized using a code block containing comma-delimited values which match in position the elements in the array
• If there are values in the initialisation block, but not enough to fill the array, all the elements in the array without values are initialized to 0 in the case of float or int, and NULL in the case of char
March 2006 Basis-C-5/LL 12
• If there are values in the initialization block, an explicit size for the array does not need to be specified, only an empty array element operator. C will count the values and size the array for you
Initialising arrays 2
March 2006 Basis-C-5/LL 13
Examples
int x [ 5 ] = { 1,2,3,4,5 }; size 20 bytes– creates array with elements 0-4 values 1-5
int x [ 5 ] = { 4,3 }; size 20 bytes– creates array with elements 0-4 values 4,3,0,0,0
int x [ ] = { 1,2,3 }; size 12 bytes– creates array with elements 0-2 values 1,2,3
char c [ 4 ] = { ‘M’ , ‘o’ , ‘o’ }; size 4 bytes– creates array with elements 0-3 values M o o NULL
March 2006 Basis-C-5/LL 14
Terminology
• A value in an array is called an array element
• The number of elements stored in an array is called the array length
• A subscript is an integer expression enclosed in [ ] that when used in combination with the array name designates a particular element in an array
March 2006 Basis-C-5/LL 15
Declaration
• Examplesint j[100];
double x[20];
j is a 100 element integer array
x is a 20 element floating point array
March 2006 Basis-C-5/LL 16
Dimensionality
• The number of subscripts determines the dimensionality of an array
• x[i] refers to an element of a one dimensional array x
• y[i] [j] refers to an element of a two dimensional array y
• z[i] [j] [k] refers to an element of a three dimensional array z
• Etc.
March 2006 Basis-C-5/LL 17
Dimensionality 2
• Variable size array declarations are not allowed, e.g. double a[n];
• Remember that size is the number of elements, hence things like a[-24] and b[37.7] are not allowed
• It might be convenient to use a symbolic constant and not a fixed integer– Makes modification easier, e.g.
#define N 100int array_num[N];
March 2006 Basis-C-5/LL 18
Single v. multi-dimensional
• So far, we have only looked at single dimensional arrays• E.g. we can represent one row of data
int numbers[5] = {2,4,6,7,4};
• A two dimensional array is similar to creating a table of data (also similar to a Microsoft Excel spreadsheet.)
• You can also create 3, 4, 5 dimensional arrays– In fact, the ANSI C specification states that compilers must be able to
support up to 12 dimensions
• Beyond 2 dimensions, however, things can get confusing. So, we will stick to 2 for now
March 2006 Basis-C-5/LL 19
Why use 2-D arrays?
• 2-D arrays are useful for lots of applications– Anything that you would put in a table fits nicely
into a 2-D array– Track company stock price for 5 different
companies over 30 days. (just create a 5 x 30 array.)
– Track homework grades for 5 homework assignments completed by 55 students (just create a 5 x 55 array.)
March 2006 Basis-C-5/LL 20
Declaring 2D arrays
• To declare a 1-D Array, we specify 1 size data_type array_name [size];
• To declare a 2-D Array, we specify 2 sizesdata_type array_name[# of rows][# of columns]
• Examplesint a[2][3]; /* Creates a 2x3 array of ints */
double b[5][2] /* Creates a 5x2 array of doubles */
March 2006 Basis-C-5/LL 21
Initializing 2-D arrays
• To initialize a 1-D Array, just place all your data inside of brackets { }
• To initialize a 2-D Array, place your data inside of embedded brackets { {},{} }
March 2006 Basis-C-5/LL 22
int b[2][2] = { {1}, {3, 4}};
• This one line will create a 2 x 2 array and initialise the array as follows
1 0
3 4
0 1
0
1
Columns
Rows
Note: In this case, we provide one data elementfor the first row. After this, all remaining elementsin the row are initialisedto 0
Initialising a 2D array
March 2006 Basis-C-5/LL 23
Referencing 2D arrays
• To reference a 2D Array, you need to specify a row/column coordinate array_name[row #][column #]
• Remember that coordinate always start at 0
March 2006 Basis-C-5/LL 24
• Assuming we have the following array b:• Assuming we have the following array b:
printf ("%d", b[0][0]); /* prints 1 */
printf ("%d", b[1][0]); /* prints 3 */
printf ("%d", b[1][1]); /* prints 4 */
1 0
3 4
0 1
0
1
Examples
March 2006 Basis-C-5/LL 25
Array example//input ten numbers and print them out backwards#include <stdio.h>main() {
int i, num[10];for (i=0; i<10; i++) {
printf(“Please enter an integer: ”); scanf(“%d”, &num[i]); } for (i=9; i>=0; i--) printf(“ %d”, num[i]);}
March 2006 Basis-C-5/LL 26
Another array example
//Find the lowest number in the array num[10]int min, i;min = num[0];for (i=1; i<10; i++) {
if (num[i] < min) min = num[i];
}printf(“The minimum is %d”, min);
March 2006 Basis-C-5/LL 27
Variable addresses
• Variables have two values associated with them: their content and their address
• A pointer is a variable which stores the memory address of another variable
• Consider a program which includes the following declarations
int num = 0, peter = 57;char letter = ‘f’;
March 2006 Basis-C-5/LL 28
Variable addresses 2
Name letter num peter
Address 10045 10046 10050
Value ‘f’ 0 57
March 2006 Basis-C-5/LL 29
Variable addresses 3
• Addresses are allocated by the compiler • Unlike contents, the address of the variable can
not change during its lifetime• The address of a given variable may differ each
time the program is run• The & operator gives the address of a variable
Using the previous example&letter is 10045&num is 10046
March 2006 Basis-C-5/LL 30
Pointers
• Pointer are a fundamental part of C. The secret to C is in its use of pointers
• Pointers are (perhaps?) the most difficult part of C to understand
• So - what is a pointer?• A pointer is a variable which contains the
address in memory of another variable. A pointer must have a certain type
March 2006 Basis-C-5/LL 31
Pointers 2
• Pointers hold memory addresses– char * - holds memory address of a character variable
– int * - holds memory address of an integer variable
– Student * - holds memory address of a Student variable
• All pointers are of the same size regardless of what they point to (because memory addresses are all within the same range of values)
March 2006 Basis-C-5/LL 32
Pointer Syntax
• &<variable> – reference operator
– returns the memory address of that variable
– result is a pointer to whatever type the variable is
• *<pointer variable> – dereference operator
– accesses the memory address stored in the pointer
– result is of whatever type the original variable was
March 2006 Basis-C-5/LL 33
Pointers and arrays
• The name of an array (with no subscript) is equivalent to a pointer to the first item in the array
int numArray[10];int * numArrayPtr;numArrayPtr = numArray;numArray[0] = 5;printf(“Ptr: %d\n”, *numArrayPtr);
March 2006 Basis-C-5/LL 34
Pointers and arrays 2
• A pointer to the first item in an array is as good as the array itself
• Remember that an array is a contiguous block of memory
• If we have the location of the first item, and we know how much memory each item takes up, we can get to the next item easily
March 2006 Basis-C-5/LL 35
Generic Pointer
• Pointers are all the same size underneath
• Sometimes it is convenient to treat all pointer types interchangeably
• Generic pointer type: void *
• Function that expects void * can take any pointer as argument
• Important in malloc/free (more later)
March 2006 Basis-C-5/LL 36
Giving a pointer a value
• Since a pointer always holds an address, the pointer can be given a value by using the “address of” operator & together with a variable of the same type as the pointer
• A pointer must be given a value before you can dereference it (it has to point to something)
char* pc; char c = ‘y’; pc = &c;
March 2006 Basis-C-5/LL 37
Dereferencing a pointer
• The dereference operator * is used to get the value stored at a memory location
• To dereference a pointer, we simply prefix it with the dereference operator
char* pc;char c=‘Y’, c2 = ‘N’;pc = &c;c2 = *pc;
March 2006 Basis-C-5/LL 39
How pointers work
• Instead of referring to a variable directly, pointers provide the location where the variable exists in memory
• This is useful when you want to change a variable in memory within a function– Normally a function copies its arguments and changes
to the passed arguments to not affect the main program– If you pass a pointer, then when you change the values
at the address pointed to, the changes do affect the main program
March 2006 Basis-C-5/LL 40
The value of pointers
• If we pass a variable to a function, a copy of the variable’s value is taken by the receiving parameter
• If this value is a pointer, however, a copy of the address is passed. This address can then be dereferenced and the value of the address read and/or changed
• This allows us to change a variable when it is not in scope
March 2006 Basis-C-5/LL 42
Passing an array#include <stdio.h>void fun ( int * )int main(void)
{int array[ ] = { 1 , 2 , 3 , 4 , 5 };fun ( array );return 0;}
void fun ( int * x ){printf ( “%d” , x[3] ); // Will print 4return;}
March 2006 Basis-C-5/LL 43
Pointer example#include <stdio.h>void AddTen( int*);int main(void)
{int x;printf (“Enter a number:”);scanf ( “%d” , &x ); //User enters 12AddTen( &x );printf (“The value of x is %d” , x); //Prints 22 (x changed!)return 0;}
void AddTen( int *p ) //p holds the address of x{ *p = *p + 10; //&x is the same as p so x is the same as *preturn;}
March 2006 Basis-C-5/LL 44
Using pointers
• Given a variable y of type int*, how do we use the value at the address y points to?– The * operator lets us get the information out of
the address y– The statement *y says “give me the information
of the variable that y is pointing to”
March 2006 Basis-C-5/LL 45
Example
int main() {
int x = 10;
int* y = &x;
printf(“%d\n”, *y);
}
Prints the value 10 – the value in the variable at the address stored in y
In other words, the value to which y points
March 2006 Basis-C-5/LL 46
Another example
int main() {int x = 10;int* y = &x;x = 20;printf(“%d\n”, *y);
}Prints the value 20y points to x, so changing x changes *y
March 2006 Basis-C-5/LL 47
Swap example
• If we need a function to swap two values a and b, we cannot always just use swap(a,b)
• Instead we need to swap pointers to a and b, i.e. swap(&a,&b)
• Prototype for swap function must state that a pointer is being sent
March 2006 Basis-C-5/LL 48
#include <stdio.h>
void swap(int *, int *);
int main(void){
int a = 3, b = 7;
printf(“%d %d\n”, a, b); // 3 7 is printedswap(&a, &b); printf(“%d %d\n”, a, b); // 7 3 is printedretun 0;
}
void swap(int *p, int *q){
int tmp;
tmp = *p;*p = *q;*q = tmp;
}
March 2006 Basis-C-5/LL 49
Pointer arithmetic
• C even allows the use of pointer arithmeticpa = pa + 5; is the same as pa=&(pa[5]);
• Three operations are allowed in pointer arithmetic pointer + integer (which gives a pointer)
pointer - integer (which gives a pointer)
pointer - pointer (which gives an integer)
• The “comparison operators” (==, !=, etc.) work on pointers
March 2006 Basis-C-5/LL 50
Pointer arithmetic 2
• Now that we have pointers, we can do pointer arithmeticint *y = &x;
y = y+1;
• The y = y+1 will set y to the address of the “next” integer after x– If x has address 0, then it uses bytes 0, 1, 2, 3
March 2006 Basis-C-5/LL 52
A picture of int arr[x]
• Assuming arr==0 (it holds the address 0)
• arr[0] is at address 0 – which is equal to arr
• arr[1] is at address 4 – which is equal to arr+1
• arr[2] is at address 8– which is equal to arr+2
• arr[3] is at address 12– which is equal to arr+3
• arr[4] is at address 16– which is equal to arr+4
March 2006 Basis-C-5/LL 53
Exampleint main() {
int arr[20];int i;for (i=0; i < 20; i++) {
*(arr+i) = 20-i; //Assigns values to the array}for (i=0; i < 20; i++) {
printf(“%d ”, arr[i]); // Prints the values}
}
March 2006 Basis-C-5/LL 54
Explanation
• The example prints all numbers from 1 to 20
• In the example, we access the elements in two different ways– In the first loop, we use pointer arithmetic– In the second loop, we use the [] operator– They do the same thing – we could have used
either method for either loop
March 2006 Basis-C-5/LL 55
Dynamic memory allocation
• Declaring variables of fixed size allocates memory in a static way – variables do not change as program runs
• Can also declare memory dynamically– Allocate different amounts of memory from run
to run of the program– Increase/reduce amount of memory as program
runs
March 2006 Basis-C-5/LL 56
• ANSI C provides four functions to manage dynamic memory– malloc and calloc are used to allocate memory– realloc is used to reallocate memory– free is used to release memory
Dynamic memory allocation 2
March 2006 Basis-C-5/LL 57
Allocating memory
• The parameter to malloc is the number of bytes of memory required
• The sizeof operator is often used to determine the required size
• Example call to mallocint *p, height;p = (int *) malloc(sizeof(height));or p = (int *)malloc(sizeof(int));
March 2006 Basis-C-5/LL 58
malloc• Part of the stdlib.h system file • Returns a void* pointer to the first byte in the
sequence• malloc() takes the number of bytes to allocate• returns void * pointer holding the address of the
chunk of memory that was allocated
• Problems– need to calculate the number of bytes– need to use the void * pointer as pointer of type you
want to use (eg, int *, char *)
March 2006 Basis-C-5/LL 59
Using malloc
char * str = NULL;
// allocate 10 consecutive bytes to be used to store char values
str = (char *)malloc(10);
// when finished, clean up
free(str);
March 2006 Basis-C-5/LL 60
Variable-sized arrays
• With malloc, we have a way of declaring arrays whose sizes are not known at runtime
int* arr = (int*)malloc(n*sizeof(int))– This will reserve space for an int array of size
n, whatever n happens to be at the time
March 2006 Basis-C-5/LL 63
Releasing memory
• Programs which allocate storage space as they run often do not need it for the entire run
• It is important to release memory once it is no longer required
• The standard library function free provides this facility
void free( void *p);
• free releases the memory pointed to by p
• p should point to an area of storage previously allocated by malloc, calloc or realloc
March 2006 Basis-C-5/LL 64
free
• The free function frees up memory– Defined in stdlib.h– Takes a pointer of type void*
• Any pointer type used will be automatically cast
– Releases all memory that was assigned to the pointer by malloc
– Syntax: free(arr);• Technically, this is: free((void*) arr);
March 2006 Basis-C-5/LL 65
Memory management
• malloc() and free() must be used carefully to avoid bugs
• Potential problems– dangling pointers
– memory leaks
March 2006 Basis-C-5/LL 66
NULL – the null pointer
• A pointer with the address 0x0 is a null pointer
• Never dereference the null pointer – crash will occur
• Major source of bugs (common cause of ‘the blue screen of death’)
March 2006 Basis-C-5/LL 67
NULL pointers
• stdlib.h holds the following directive #define NULL 0
• NULL is used to indicate that a pointer is “not pointing to anything”
• We can then use it in a statement like if (x==NULL) {
x = (int*) malloc(10*sizeof(x)); }
March 2006 Basis-C-5/LL 68
Protecting against null pointers
• Always initialize all pointers to NULL when declaring them
• NULL and the null character both equivalent to false– Can be used in conditional statements
March 2006 Basis-C-5/LL 69
#include <stdio.h>
void bubble(int a[], int n); void prn_array(char* s, int a[], int n); void swap(int *p, int *q);
int main(void) {
int a[] = {7, 3, 66, 3, -5, 22, -77, 2}; int n; n = sizeof(a) / sizeof(int);
prn_array("Before", a, n); bubble(a, n); /* bubble sort */ prn_array(" After", a, n); putchar('\n'); return 0;
}
void bubble(int a[], int n) /* n is the size of a[] */ {
int i, j;
for (i = 0; i < n - 1; ++i) for (j = n - 1; i < j; --j)
if (a[j-1] > a[j]) swap(&a[j-1], &a[j]);
}
March 2006 Basis-C-5/LL 70
void prn_array(char* s, int a[], int n)
{
int i;
printf("\n%s%s%s", " ", s, " sorting:");
for (i = 0; i < n; ++i)
printf("%5d", a[i]);
putchar('\n');
}
void swap(int *p, int *q)
{
int tmp;
tmp = *p;
*p = *q;
*q = tmp;
}