C Programming Language
Mo’meN Ali
Arrays and Pointers
#include <stdio.h>
#define MONTHS 12
int main(void)
{
int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
int index;
for (index = 0; index < MONTHS; index++)
printf("Month %d has %2d days.n", index +1,
days[index]);
return 0;
}
Output
Month 1 has 31 days.
Month 2 has 28 days.
Month 3 has 31 days.
Month 4 has 30 days.
Month 5 has 31 days.
Month 6 has 30 days.
Month 7 has 31 days.
Month 8 has 31 days.
Month 9 has 30 days.
Month 10 has 31 days.
Month 11 has 30 days.
Month 12 has 31 days.
#include <stdio.h>
#define SIZE 4
int main(void)
{
int some_data[SIZE] = {1492, 1066};
int i;
printf("%2s%14sn", i, some_data[i]);
for (i = 0; i < SIZE; i++)
printf("%2d%14dn", i, some_data[i]);
return 0;
}
Output
i some_data[i]
0 1492
1 1066
2 0
3 0
#include <stdio.h>
int main(void)
{
const int days[] = {31,28,31,30,31,30,31,31,30,31};
int index;
for (index = 0; index < sizeof days / sizeof days[0]; index++)
printf("Month %2d has %d days.n", index +1,
days[index]);
return 0;
}
Output
Month 1 has 31 days.
Month 2 has 28 days.
Month 3 has 31 days.
Month 4 has 30 days.
Month 5 has 31 days.
Month 6 has 30 days.
Month 7 has 31 days.
Month 8 has 31 days.
Month 9 has 30 days.
Month 10 has 31 days.
Designated Initializers (C99)
C99 has added a new capability—designated initializers. This feature allows you to
pick and
choose which elements are initialized. Suppose, for example, that you just want to
initialize the
last element in an array. With traditional C initialization syntax, you also have to
initialize every
element preceding the last one:
int arr[6] = {0,0,0,0,0,212}; // traditional syntax
With C99, you can use an index in brackets in the initialization list to specify a
particular
element:
int arr[6] = {[5] = 212}; // initialize arr[5] to 212
Array Bounds
You have to make sure you use array indices that are within bounds; that is, you
have to make
sure they have values valid for the array. For instance, suppose you make the
following
declaration:
int doofi[20];
Then it's your responsibility to make sure the program uses indices only in the range
0 through
19, because the compiler won't check for you.
#include <stdio.h>
#define SIZE 4
int main(void)
{
int value1 = 44;
int arr[SIZE];
int value2 = 88;
int i;
printf("value1 = %d, value2 = %dn", value1, value2);
for (i = -1; i <= SIZE; i++)
arr[i] = 2 * i + 1;
for (i = -1; i < 7; i++)
printf("%2d %dn", i , arr[i]);
printf("value1 = %d, value2 = %dn", value1, value2);
return 0;
}
Output
value1 = 44, value2 = 88
-1 -1
0 1
1 3
2 5
3 7
4 9
5 5
6 1245120
value1 = -1, value2 = 9
Multidimensional Arrays [Array of arrays]
A multidimensional array is an array which every element in it is an array.
float rain[5] [12]; // an array of 12 floats
This tells us that each element is of type float[12]; that is, each of the five elements
of rain is, in itself, an array of 12 float values.
#include <stdio.h>
#define MONTHS 12 // number of months in a year
#define YEARS 5 // number of years of data
int main(void)
{
// initializing rainfall data for 2000 - 2004
const float rain[YEARS][MONTHS] = {
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
{8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3},
{9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
{7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
{7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}
};
int year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)n");
for (year = 0, total = 0; year < YEARS; year++)
{ // for each year, sum rainfall for each month
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += rain[year][month];
printf("%5d %15.1fn", 2000 + year, subtot);
total += subtot; // total for all years
}
printf("nThe yearly average is %.1f inches.nn", total/YEARS);
printf("MONTHLY AVERAGES:nn");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" Nov Decn");
for (month = 0; month < MONTHS; month++)
{ // for each month, sum rainfall over years
for (year = 0, subtot =0; year < YEARS; year++)
subtot += rain[year][month];
printf("%4.1f ", subtot/YEARS);
}
printf("n");
return 0;
}
Output
YEAR RAINFALL (inches)
2000 32.4
2001 37.9
2002 49.8
2003 44.0
2004 32.9
The yearly average is 39.4 inches.
MONTHLY AVERAGES:
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov
Dec
7.3 7.3 4.9 3.0 2.3 0.6 1.2 0.3 0.5 1.7 3.6 6.7
Pointers and Arrays
Array notation is simply a disguised use of pointers.
An example of this disguised use is that an array name is also the address of the
first element of the array. That is, if flizny is an array, the following is true:
flizny == &flizny[0]; // name of array is the address of the first element
Both flizny and &flizny[0] represent the memory address of that first element.
#include <stdio.h>
#define SIZE 4
int main(void)
{
short dates [SIZE];
short * pti;
short index;
double bills[SIZE];
double * ptf;
pti = dates; // assign address of array to pointer
ptf = bills;
printf("%23s %10sn", "short", "double");
for (index = 0; index < SIZE; index ++)
printf("pointers + %d: %10p %10pn", index, pti + index, ptf + index);
return 0;
}
Output
pointers + 0: 0x0064fd20 0x0064fd28
pointers + 1: 0x0064fd22 0x0064fd30
pointers + 2: 0x0064fd24 0x0064fd38
pointers + 3: 0x0064fd26 0x0064fd40
Some conventions
dates +2 == &date[2] /* same address */
*(dates + 2) == dates[2] /* same value */
*(dates +2) /* value of the 3rd element of dates */
*dates +2 /* 2 added to the value of the 1st element */
#include <stdio.h>
#define MONTHS 12
int main(void)
{
int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
int index;
for (index = 0; index < MONTHS; index++)
printf("Month %2d has %d days.n", index +1,
*(days + index)); // same as days[index]
return 0;
}
Output
Month 1 has 31 days.
Month 2 has 28 days.
Month 3 has 31 days.
Month 4 has 30 days.
Month 5 has 31 days.
Month 6 has 30 days.
Month 7 has 31 days.
Month 8 has 31 days.
Month 9 has 30 days.
Month 10 has 31 days.
Month 11 has 30 days.
Month 12 has 31 days.
Functions, Arrays, and Pointers
Suppose you want to write a function that operates on an array. For
example, suppose you want a function that returns the sum of the
elements of an array. Suppose marbles is the name of an
array of int. What would the function call look like? A reasonable
guess would be this:
total = sum(marbles); // possible function call
// function prototypes
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);
// sum_arr1.c -- sums the elements of an array
// use %u or %lu if %zd doesn't work
#include <stdio.h>
#define SIZE 10
int sum(int ar[], int n);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sum(marbles, SIZE);
printf("The total number of marbles is %ld.n", answer);
printf("The size of marbles is %zd bytes.n",
sizeof (marbles));
return 0;
}
int sum(int ar[], int n) // how big an array?
{
int i;
int total = 0;
for( i = 0; i < n; i++)
total += ar[i];
printf("The size of ar is %zd bytes.n", sizeof (ar));
return total;
}
Output
The size of ar is 4 bytes.
The total number of marbles is 190.
The size of marbles is 40 bytes.
#include <stdio.h>
#define SIZE 10
int sump(int * start, int * end);
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sump(marbles, marbles + SIZE);
printf("The total number of marbles is %ld.n", answer);
return 0;
}
/* use pointer arithmetic */
int sump(int * start, int * end)
{
int total = 0;
while (start < end)
{
total += *start; /* add value to total */
start++; /* advance pointer to next element */
}
return total;
}
/* order.c -- precedence in pointer operations */
#include <stdio.h>
int data[2] = {100, 200};
int moredata[2] = {300, 400};
int main(void)
{
int * p1, * p2, * p3;
p1 = p2 = data;
p3 = moredata;
printf(" *p1 = %d, *p2 = %d, *p3 = %dn",
*p1, *p2, *p3);
printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %dn",
*p1++, *++p2, (*p3)++);
printf(" *p1 = %d, *p2 = %d, *p3 = %dn",
*p1, *p2, *p3);
return 0;
}
Output
*p1 = 100, *p2 = 100, *p3 = 300
*p1++ = 100, *++p2 = 200, (*p3)++ = 300
*p1 = 200, *p2 = 200, *p3 = 301
#include <stdio.h>
int main(void)
{
int urn[5] = {100,200,300,400,500};
int * ptr1, * ptr2, *ptr3;
ptr1 = urn; // assign an address to a pointer
ptr2 = &urn[2]; // ditto
// dereference a pointer and take
// the address of a pointer
printf("pointer value, dereferenced pointer, pointer address:n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %pn",
ptr1, *ptr1, &ptr1);
// pointer addition
ptr3 = ptr1 + 4;
printf("nadding an int to a pointer:n");
printf("ptr1 + 4 = %p, *(ptr1 + 3) = %dn",
ptr1 + 4, *(ptr1 + 3));
ptr1++; // increment a pointer
printf("nvalues after ptr1++:n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %pn",
ptr1, *ptr1, &ptr1);
ptr2--; // decrement a pointer
printf("nvalues after --ptr2:n");
printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %pn",
ptr2, *ptr2, &ptr2);
--ptr1; // restore to original value
++ptr2; // restore to original value
printf("nPointers reset to original values:n");
printf("ptr1 = %p, ptr2 = %pn", ptr1, ptr2);
// subtract one pointer from another
printf("nsubtracting one pointer from another:n");
printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %dn",
ptr2, ptr1, ptr2 - ptr1);
// subtract an integer from a pointer
printf("nsubtracting an int from a pointer:n");
printf("ptr3 = %p, ptr3 - 2 = %pn",
ptr3, ptr3 - 2);
return 0;
}
Output
pointer value, dereferenced pointer, pointer address:
ptr1 = 0x0012ff38, *ptr1 =100, &ptr1 = 0x0012ff34
adding an int to a pointer:
ptr1 + 4 = 0x0012ff48, *(ptr4 + 3) = 400
values after ptr1++:
ptr1 = 0x0012ff3c, *ptr1 =200, &ptr1 = 0x0012ff34
values after --ptr2:
ptr2 = 0x0012ff3c, *ptr2 = 200, &ptr2 = 0x0012ff30
Pointers reset to original values:
ptr1 = 0x0012ff38, ptr2 = 0x0012ff40
subtracting one pointer from another:
ptr2 = 0x0012ff40, ptr1 = 0x0012ff38, ptr2 - ptr1 = 2
subtracting an int from a pointer:
ptr3 = 0x0012ff48, ptr3 - 2 = 0x0012ff40
#include <stdio.h>
#define SIZE 5
void show_array(const double ar[], int n);
void mult_array(double ar[], int n, double mult);
int main(void)
{
double dip[SIZE] = {20.0, 17.66, 8.2, 15.3, 22.22};
printf("The original dip array:n");
show_array(dip, SIZE);
mult_array(dip, SIZE, 2.5);
printf("The dip array after calling mult_array():n");
show_array(dip, SIZE);
return 0;
}
/* displays array contents */
void show_array(const double ar[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%8.3f ", ar[i]);
putchar('n');
}
/* multiplies each array member by the same multiplier */
void mult_array(double ar[], int n, double mult)
{
int i;
for (i = 0; i < n; i++)
ar[i] *= mult;
}
Output
The original dip array:
20.000 17.660 8.200 15.300 22.220
The dip array after calling mult_array():
50.000 44.150 20.500 38.250 55.550
int zippo[4][2]; /* an array of arrays of ints */
Then zippo, being the name of an array, is the address of the first element of the
array. In this case, the first element of zippo is itself an array of two ints, so zippo is
the address of an array of two ints.
Pointers and Multidimensional Arrays
#include <stdio.h>
int main(void)
{
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} };
printf(" zippo = %p, zippo + 1 = %pn",
zippo, zippo + 1);
printf("zippo[0] = %p, zippo[0] + 1 = %pn",
zippo[0], zippo[0] + 1);
printf(" *zippo = %p, *zippo + 1 = %pn",
*zippo, *zippo + 1);
printf("zippo[0][0] = %dn", zippo[0][0]);
printf(" *zippo[0] = %dn", *zippo[0]);
printf(" **zippo = %dn", **zippo);
printf(" zippo[2][1] = %dn", zippo[2][1]);
printf("*(*(zippo+2) + 1) = %dn", *(*(zippo+2) + 1));
return 0;
}
Output
zippo = 0x0064fd38, zippo + 1 = 0x0064fd40
zippo[0] = 0x0064fd38, zippo[0] + 1 = 0x0064fd3c
*zippo = 0x0064fd38, *zippo + 1 = 0x0064fd3c
zippo[0][0] = 2
*zippo[0] = 2
**zippo = 2
zippo[1][2] = 3
*(*(zippo+1) + 2) = 3
Zippo the address of the first two-int element .
Zippo+2 the address of the third two-int element.
*(zippo+2) the third element, a two-int array, hence the address of its
first element, an int.
*(zippo+2) + 1 the address of the second element of the two-int array, also
an int.
*(*(zippo+2) + 1) the value of the second int in the third row (zippo[2][1]).
How would you declare a pointer variable pz that can point to a two-dimensional array
such as zippo? Such a pointer could be used, for example, in writing a function to deal
with zippo-like arrays. Will the type pointer-to-int suffice? No. That type is compatible
with zippo[0], which points to a single int. But zippo is the address of its first element,
which is an array of two ints. Hence, pz must point to an array of two ints, not to a
single int. Here is what you can do:
int (* pz)[2]; // pz points to an array of 2 ints
This statement says that pz is a pointer to an array of two ints. Why the parentheses?
Well, [ ] has a higher precedence than *.
Pointers to Multidimensional Arrays
#include <stdio.h>
int main(void)
{
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} };
int (*pz)[2];
pz = zippo;
printf(" pz = %p, pz + 1 = %pn",
pz, pz + 1);
printf("pz[0] = %p, pz[0] + 1 = %pn",
pz[0], pz[0] + 1);
printf(" *pz = %p, *pz + 1 = %pn",
*pz, *pz + 1);
printf("pz[0][0] = %dn", pz[0][0]);
printf(" *pz[0] = %dn", *pz[0]);
printf(" **pz = %dn", **pz);
printf(" pz[2][1] = %dn", pz[2][1]);
printf("*(*(pz+2) + 1) = %dn", *(*(pz+2) + 1));
return 0;
}
Output
pz = 0x0064fd38, pz + 1 = 0x0064fd40
pz[0] = 0x0064fd38, pz[0] + 1 = 0x0064fd3c
*pz = 0x0064fd38, *pz + 1 = 0x0064fd3c
pz[0][0] = 2
*pz[0] = 2
**pz = 2
pz[2][1] = 3
*(*(pz+2) + 1) = 3
Pointer Compatibility
The rules for assigning one pointer to another are tighter than the rules for numeric
types. For example, you can assign an int value to a double variable without using a
type conversion, but you can't do the same for pointers to these two types
#include <stdio.h>
#define ROWS 3
#define COLS 4
void sum_rows(int ar[][COLS], int rows);
void sum_cols(int [][COLS], int ); // ok to omit names
int sum2d(int (*ar)[COLS], int rows); // another syntax
int main(void)
{
int junk[ROWS][COLS] = {
{2,4,6,8},
{3,5,7,9},
{12,10,8,6}
};
sum_rows(junk, ROWS);
sum_cols(junk, ROWS);
printf("Sum of all elements = %dn", sum2d(junk, ROWS));
return 0;
}
void sum_rows(int ar[][COLS], int rows)
{
int r;
int c;
int tot;
for (r = 0; r < rows; r++)
{
tot = 0;
for (c = 0; c < COLS; c++)
tot += ar[r][c];
printf("row %d: sum = %dn", r, tot);
}
}
void sum_cols(int ar[][COLS], int rows)
{
int r;
int c;
int tot;
for (c = 0; c < COLS; c++)
{
tot = 0;
for (r = 0; r < rows; r++)
tot += ar[r][c];
printf("col %d: sum = %dn", c, tot);
}
}
int sum2d(int ar[][COLS], int rows)
{
int r;
int c;
int tot = 0;
for (r = 0; r < rows; r++)
for (c = 0; c < COLS; c++)
tot += ar[r][c];
return tot;
}
Output
row 0: sum = 20
row 1: sum = 24
row 2: sum = 36
col 0: sum = 17
col 1: sum = 19
col 2: sum = 21
col 3: sum = 23
Sum of all elements = 80
Variable-Length Arrays (VLAs)
Compound Literals
Search yourself

8 arrays and pointers

  • 1.
  • 2.
  • 3.
    #include <stdio.h> #define MONTHS12 int main(void) { int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31}; int index; for (index = 0; index < MONTHS; index++) printf("Month %d has %2d days.n", index +1, days[index]); return 0; }
  • 4.
    Output Month 1 has31 days. Month 2 has 28 days. Month 3 has 31 days. Month 4 has 30 days. Month 5 has 31 days. Month 6 has 30 days. Month 7 has 31 days. Month 8 has 31 days. Month 9 has 30 days. Month 10 has 31 days. Month 11 has 30 days. Month 12 has 31 days.
  • 5.
    #include <stdio.h> #define SIZE4 int main(void) { int some_data[SIZE] = {1492, 1066}; int i; printf("%2s%14sn", i, some_data[i]); for (i = 0; i < SIZE; i++) printf("%2d%14dn", i, some_data[i]); return 0; }
  • 6.
  • 7.
    #include <stdio.h> int main(void) { constint days[] = {31,28,31,30,31,30,31,31,30,31}; int index; for (index = 0; index < sizeof days / sizeof days[0]; index++) printf("Month %2d has %d days.n", index +1, days[index]); return 0; }
  • 8.
    Output Month 1 has31 days. Month 2 has 28 days. Month 3 has 31 days. Month 4 has 30 days. Month 5 has 31 days. Month 6 has 30 days. Month 7 has 31 days. Month 8 has 31 days. Month 9 has 30 days. Month 10 has 31 days.
  • 9.
    Designated Initializers (C99) C99has added a new capability—designated initializers. This feature allows you to pick and choose which elements are initialized. Suppose, for example, that you just want to initialize the last element in an array. With traditional C initialization syntax, you also have to initialize every element preceding the last one: int arr[6] = {0,0,0,0,0,212}; // traditional syntax With C99, you can use an index in brackets in the initialization list to specify a particular element: int arr[6] = {[5] = 212}; // initialize arr[5] to 212
  • 10.
    Array Bounds You haveto make sure you use array indices that are within bounds; that is, you have to make sure they have values valid for the array. For instance, suppose you make the following declaration: int doofi[20]; Then it's your responsibility to make sure the program uses indices only in the range 0 through 19, because the compiler won't check for you.
  • 11.
    #include <stdio.h> #define SIZE4 int main(void) { int value1 = 44; int arr[SIZE]; int value2 = 88; int i; printf("value1 = %d, value2 = %dn", value1, value2); for (i = -1; i <= SIZE; i++) arr[i] = 2 * i + 1; for (i = -1; i < 7; i++) printf("%2d %dn", i , arr[i]); printf("value1 = %d, value2 = %dn", value1, value2); return 0; }
  • 12.
    Output value1 = 44,value2 = 88 -1 -1 0 1 1 3 2 5 3 7 4 9 5 5 6 1245120 value1 = -1, value2 = 9
  • 13.
    Multidimensional Arrays [Arrayof arrays] A multidimensional array is an array which every element in it is an array. float rain[5] [12]; // an array of 12 floats This tells us that each element is of type float[12]; that is, each of the five elements of rain is, in itself, an array of 12 float values.
  • 14.
    #include <stdio.h> #define MONTHS12 // number of months in a year #define YEARS 5 // number of years of data int main(void) { // initializing rainfall data for 2000 - 2004 const float rain[YEARS][MONTHS] = { {4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6}, {8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3}, {9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4}, {7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2}, {7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2} }; int year, month; float subtot, total; printf(" YEAR RAINFALL (inches)n");
  • 15.
    for (year =0, total = 0; year < YEARS; year++) { // for each year, sum rainfall for each month for (month = 0, subtot = 0; month < MONTHS; month++) subtot += rain[year][month]; printf("%5d %15.1fn", 2000 + year, subtot); total += subtot; // total for all years } printf("nThe yearly average is %.1f inches.nn", total/YEARS); printf("MONTHLY AVERAGES:nn"); printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct "); printf(" Nov Decn"); for (month = 0; month < MONTHS; month++) { // for each month, sum rainfall over years for (year = 0, subtot =0; year < YEARS; year++) subtot += rain[year][month]; printf("%4.1f ", subtot/YEARS); } printf("n"); return 0; }
  • 16.
    Output YEAR RAINFALL (inches) 200032.4 2001 37.9 2002 49.8 2003 44.0 2004 32.9 The yearly average is 39.4 inches. MONTHLY AVERAGES: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 7.3 7.3 4.9 3.0 2.3 0.6 1.2 0.3 0.5 1.7 3.6 6.7
  • 17.
    Pointers and Arrays Arraynotation is simply a disguised use of pointers. An example of this disguised use is that an array name is also the address of the first element of the array. That is, if flizny is an array, the following is true: flizny == &flizny[0]; // name of array is the address of the first element Both flizny and &flizny[0] represent the memory address of that first element.
  • 18.
    #include <stdio.h> #define SIZE4 int main(void) { short dates [SIZE]; short * pti; short index; double bills[SIZE]; double * ptf; pti = dates; // assign address of array to pointer ptf = bills; printf("%23s %10sn", "short", "double"); for (index = 0; index < SIZE; index ++) printf("pointers + %d: %10p %10pn", index, pti + index, ptf + index); return 0; }
  • 19.
    Output pointers + 0:0x0064fd20 0x0064fd28 pointers + 1: 0x0064fd22 0x0064fd30 pointers + 2: 0x0064fd24 0x0064fd38 pointers + 3: 0x0064fd26 0x0064fd40
  • 20.
    Some conventions dates +2== &date[2] /* same address */ *(dates + 2) == dates[2] /* same value */ *(dates +2) /* value of the 3rd element of dates */ *dates +2 /* 2 added to the value of the 1st element */
  • 21.
    #include <stdio.h> #define MONTHS12 int main(void) { int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31}; int index; for (index = 0; index < MONTHS; index++) printf("Month %2d has %d days.n", index +1, *(days + index)); // same as days[index] return 0; }
  • 22.
    Output Month 1 has31 days. Month 2 has 28 days. Month 3 has 31 days. Month 4 has 30 days. Month 5 has 31 days. Month 6 has 30 days. Month 7 has 31 days. Month 8 has 31 days. Month 9 has 30 days. Month 10 has 31 days. Month 11 has 30 days. Month 12 has 31 days.
  • 23.
    Functions, Arrays, andPointers Suppose you want to write a function that operates on an array. For example, suppose you want a function that returns the sum of the elements of an array. Suppose marbles is the name of an array of int. What would the function call look like? A reasonable guess would be this: total = sum(marbles); // possible function call // function prototypes int sum(int *ar, int n); int sum(int *, int); int sum(int ar[], int n); int sum(int [], int);
  • 24.
    // sum_arr1.c --sums the elements of an array // use %u or %lu if %zd doesn't work #include <stdio.h> #define SIZE 10 int sum(int ar[], int n); int main(void) { int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20}; long answer; answer = sum(marbles, SIZE); printf("The total number of marbles is %ld.n", answer); printf("The size of marbles is %zd bytes.n", sizeof (marbles)); return 0; }
  • 25.
    int sum(int ar[],int n) // how big an array? { int i; int total = 0; for( i = 0; i < n; i++) total += ar[i]; printf("The size of ar is %zd bytes.n", sizeof (ar)); return total; }
  • 26.
    Output The size ofar is 4 bytes. The total number of marbles is 190. The size of marbles is 40 bytes.
  • 27.
    #include <stdio.h> #define SIZE10 int sump(int * start, int * end); int main(void) { int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20}; long answer; answer = sump(marbles, marbles + SIZE); printf("The total number of marbles is %ld.n", answer); return 0; }
  • 28.
    /* use pointerarithmetic */ int sump(int * start, int * end) { int total = 0; while (start < end) { total += *start; /* add value to total */ start++; /* advance pointer to next element */ } return total; }
  • 29.
    /* order.c --precedence in pointer operations */ #include <stdio.h> int data[2] = {100, 200}; int moredata[2] = {300, 400}; int main(void) { int * p1, * p2, * p3; p1 = p2 = data; p3 = moredata; printf(" *p1 = %d, *p2 = %d, *p3 = %dn", *p1, *p2, *p3); printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %dn", *p1++, *++p2, (*p3)++); printf(" *p1 = %d, *p2 = %d, *p3 = %dn", *p1, *p2, *p3); return 0; }
  • 30.
    Output *p1 = 100,*p2 = 100, *p3 = 300 *p1++ = 100, *++p2 = 200, (*p3)++ = 300 *p1 = 200, *p2 = 200, *p3 = 301
  • 31.
    #include <stdio.h> int main(void) { inturn[5] = {100,200,300,400,500}; int * ptr1, * ptr2, *ptr3; ptr1 = urn; // assign an address to a pointer ptr2 = &urn[2]; // ditto // dereference a pointer and take // the address of a pointer printf("pointer value, dereferenced pointer, pointer address:n"); printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %pn", ptr1, *ptr1, &ptr1); // pointer addition ptr3 = ptr1 + 4; printf("nadding an int to a pointer:n"); printf("ptr1 + 4 = %p, *(ptr1 + 3) = %dn", ptr1 + 4, *(ptr1 + 3));
  • 32.
    ptr1++; // incrementa pointer printf("nvalues after ptr1++:n"); printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %pn", ptr1, *ptr1, &ptr1); ptr2--; // decrement a pointer printf("nvalues after --ptr2:n"); printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %pn", ptr2, *ptr2, &ptr2); --ptr1; // restore to original value ++ptr2; // restore to original value printf("nPointers reset to original values:n"); printf("ptr1 = %p, ptr2 = %pn", ptr1, ptr2); // subtract one pointer from another printf("nsubtracting one pointer from another:n"); printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %dn", ptr2, ptr1, ptr2 - ptr1); // subtract an integer from a pointer printf("nsubtracting an int from a pointer:n"); printf("ptr3 = %p, ptr3 - 2 = %pn", ptr3, ptr3 - 2); return 0; }
  • 33.
    Output pointer value, dereferencedpointer, pointer address: ptr1 = 0x0012ff38, *ptr1 =100, &ptr1 = 0x0012ff34 adding an int to a pointer: ptr1 + 4 = 0x0012ff48, *(ptr4 + 3) = 400 values after ptr1++: ptr1 = 0x0012ff3c, *ptr1 =200, &ptr1 = 0x0012ff34 values after --ptr2: ptr2 = 0x0012ff3c, *ptr2 = 200, &ptr2 = 0x0012ff30 Pointers reset to original values: ptr1 = 0x0012ff38, ptr2 = 0x0012ff40 subtracting one pointer from another: ptr2 = 0x0012ff40, ptr1 = 0x0012ff38, ptr2 - ptr1 = 2 subtracting an int from a pointer: ptr3 = 0x0012ff48, ptr3 - 2 = 0x0012ff40
  • 34.
    #include <stdio.h> #define SIZE5 void show_array(const double ar[], int n); void mult_array(double ar[], int n, double mult); int main(void) { double dip[SIZE] = {20.0, 17.66, 8.2, 15.3, 22.22}; printf("The original dip array:n"); show_array(dip, SIZE); mult_array(dip, SIZE, 2.5); printf("The dip array after calling mult_array():n"); show_array(dip, SIZE); return 0; }
  • 35.
    /* displays arraycontents */ void show_array(const double ar[], int n) { int i; for (i = 0; i < n; i++) printf("%8.3f ", ar[i]); putchar('n'); } /* multiplies each array member by the same multiplier */ void mult_array(double ar[], int n, double mult) { int i; for (i = 0; i < n; i++) ar[i] *= mult; }
  • 36.
    Output The original diparray: 20.000 17.660 8.200 15.300 22.220 The dip array after calling mult_array(): 50.000 44.150 20.500 38.250 55.550
  • 37.
    int zippo[4][2]; /*an array of arrays of ints */ Then zippo, being the name of an array, is the address of the first element of the array. In this case, the first element of zippo is itself an array of two ints, so zippo is the address of an array of two ints. Pointers and Multidimensional Arrays
  • 38.
    #include <stdio.h> int main(void) { intzippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} }; printf(" zippo = %p, zippo + 1 = %pn", zippo, zippo + 1); printf("zippo[0] = %p, zippo[0] + 1 = %pn", zippo[0], zippo[0] + 1); printf(" *zippo = %p, *zippo + 1 = %pn", *zippo, *zippo + 1); printf("zippo[0][0] = %dn", zippo[0][0]); printf(" *zippo[0] = %dn", *zippo[0]); printf(" **zippo = %dn", **zippo); printf(" zippo[2][1] = %dn", zippo[2][1]); printf("*(*(zippo+2) + 1) = %dn", *(*(zippo+2) + 1)); return 0; }
  • 39.
    Output zippo = 0x0064fd38,zippo + 1 = 0x0064fd40 zippo[0] = 0x0064fd38, zippo[0] + 1 = 0x0064fd3c *zippo = 0x0064fd38, *zippo + 1 = 0x0064fd3c zippo[0][0] = 2 *zippo[0] = 2 **zippo = 2 zippo[1][2] = 3 *(*(zippo+1) + 2) = 3
  • 40.
    Zippo the addressof the first two-int element . Zippo+2 the address of the third two-int element. *(zippo+2) the third element, a two-int array, hence the address of its first element, an int. *(zippo+2) + 1 the address of the second element of the two-int array, also an int. *(*(zippo+2) + 1) the value of the second int in the third row (zippo[2][1]).
  • 41.
    How would youdeclare a pointer variable pz that can point to a two-dimensional array such as zippo? Such a pointer could be used, for example, in writing a function to deal with zippo-like arrays. Will the type pointer-to-int suffice? No. That type is compatible with zippo[0], which points to a single int. But zippo is the address of its first element, which is an array of two ints. Hence, pz must point to an array of two ints, not to a single int. Here is what you can do: int (* pz)[2]; // pz points to an array of 2 ints This statement says that pz is a pointer to an array of two ints. Why the parentheses? Well, [ ] has a higher precedence than *. Pointers to Multidimensional Arrays
  • 42.
    #include <stdio.h> int main(void) { intzippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} }; int (*pz)[2]; pz = zippo; printf(" pz = %p, pz + 1 = %pn", pz, pz + 1); printf("pz[0] = %p, pz[0] + 1 = %pn", pz[0], pz[0] + 1); printf(" *pz = %p, *pz + 1 = %pn", *pz, *pz + 1); printf("pz[0][0] = %dn", pz[0][0]); printf(" *pz[0] = %dn", *pz[0]); printf(" **pz = %dn", **pz); printf(" pz[2][1] = %dn", pz[2][1]); printf("*(*(pz+2) + 1) = %dn", *(*(pz+2) + 1)); return 0; }
  • 43.
    Output pz = 0x0064fd38,pz + 1 = 0x0064fd40 pz[0] = 0x0064fd38, pz[0] + 1 = 0x0064fd3c *pz = 0x0064fd38, *pz + 1 = 0x0064fd3c pz[0][0] = 2 *pz[0] = 2 **pz = 2 pz[2][1] = 3 *(*(pz+2) + 1) = 3
  • 44.
    Pointer Compatibility The rulesfor assigning one pointer to another are tighter than the rules for numeric types. For example, you can assign an int value to a double variable without using a type conversion, but you can't do the same for pointers to these two types
  • 45.
    #include <stdio.h> #define ROWS3 #define COLS 4 void sum_rows(int ar[][COLS], int rows); void sum_cols(int [][COLS], int ); // ok to omit names int sum2d(int (*ar)[COLS], int rows); // another syntax int main(void) { int junk[ROWS][COLS] = { {2,4,6,8}, {3,5,7,9}, {12,10,8,6} }; sum_rows(junk, ROWS); sum_cols(junk, ROWS); printf("Sum of all elements = %dn", sum2d(junk, ROWS)); return 0; }
  • 46.
    void sum_rows(int ar[][COLS],int rows) { int r; int c; int tot; for (r = 0; r < rows; r++) { tot = 0; for (c = 0; c < COLS; c++) tot += ar[r][c]; printf("row %d: sum = %dn", r, tot); } } void sum_cols(int ar[][COLS], int rows) { int r; int c; int tot;
  • 47.
    for (c =0; c < COLS; c++) { tot = 0; for (r = 0; r < rows; r++) tot += ar[r][c]; printf("col %d: sum = %dn", c, tot); } } int sum2d(int ar[][COLS], int rows) { int r; int c; int tot = 0; for (r = 0; r < rows; r++) for (c = 0; c < COLS; c++) tot += ar[r][c]; return tot; }
  • 48.
    Output row 0: sum= 20 row 1: sum = 24 row 2: sum = 36 col 0: sum = 17 col 1: sum = 19 col 2: sum = 21 col 3: sum = 23 Sum of all elements = 80
  • 49.