0% found this document useful (0 votes)
39 views128 pages

Chtp9 Ch07 Accessible

Uploaded by

Suhan ERGUNER
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)
39 views128 pages

Chtp9 Ch07 Accessible

Uploaded by

Suhan ERGUNER
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

C How to Program

Ninth Edition

Chapter 7
Pointers

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


Objectives
• Use pointers and pointer operators.
• Pass arguments to functions by reference using pointers.
• Understand the const qualifier’s various placements and how they
affect what operations you can perform on a variable.
• Use the sizeof operator with variables and types.
• Use pointer arithmetic to process array elements.
• Understand the close relationships among pointers, arrays and
strings.
• Define and use arrays of strings.
• Use function pointers.
• Learn about secure C programming with pointers.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


Outline (1 of 3)

7.1 Introduction

7.2 Pointer Variable Definitions and Initialization

7.3 Pointer Operators

7.4 Passing Arguments to Functions by Reference

7.5 Using the const Qualifier with Pointers


7.5.1 Converting a String to Uppercase Using a Non-Constant Pointer to Non-
Constant Data
7.5.2 Printing a String One Character at a Time Using a Non-Constant Pointer to
Constant Data
7.5.3 Attempting to Modify a Constant Pointer to Non-Constant Data
7.5.4 Attempting to Modify a Constant Pointer to Constant Data

7.6 Bubble Sort Using Pass-By-Reference

7.7 sizeof Operator


Copyright © 2022 Pearson Education, Inc. All Rights Reserved
Outline (2 of 3)

7.8 Pointer Expressions and Pointer Arithmetic


7.8.1 Pointer Arithmetic Operators
7.8.2 Aiming a Pointer at an Array
7.8.3 Adding an Integer to a Pointer
7.8.4 Subtracting an Integer from a Pointer
7.8.5 Incrementing and Decrementing a Pointer
7.8.6 Subtracting One Pointer from Another
7.8.7 Assigning Pointers to One Another
7.8.8 Pointer to void
7.8.9 Comparing Pointers

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


Outline (3 of 3)

7.9 Relationship between Pointers and Arrays


7.9.1 Pointer/Offset Notation
7.9.2 Pointer/Subscript Notation
7.9.3 Cannot Modify an Array Name with Pointer Arithmetic
7.9.4 Demonstrating Pointer Subscripting and Offsets
7.9.5 String Copying with Arrays and Pointers

7.10 Arrays of Pointers

7.11 Random-Number Simulation Case Study: Card Shuffling and Dealing

7.12 Function Pointers


7.12.1 Sorting in Ascending or Descending Order
7.12.2 Using Function Pointers to Create a Menu-Driven System

7.13 Secure C Programming


Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.1 Introduction
• In this chapter, we discuss one of C’s most powerful
features—the pointer.
• Pointers enable programs to
– accomplish pass-by-reference,
– pass functions between functions,
– manipulate strings and arrays, and
– create and manipulate dynamic data structures that
grow and shrink at execution time, such as linked
lists, queues, stacks and trees.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.2 Pointer Variable Definitions and
Initialization (1 of 3)
• A pointer contains the address of another variable that contains a specific value

• The pointer points to that variable

• A variable name directly references a value

• A pointer indirectly references a value

• Referencing a value through a pointer is called indirection

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.2 Pointer Variable Definitions and
Initialization (2 of 3)
Declaring Pointers
• Define countPtr as an int *—a pointer to an integer:
– int *countPtr;
• Read right-to-left, “countPtr is a pointer to int” or “countPtr
points to an object of type int.”
• * indicates that the variable is a pointer.

Pointer Variable Naming


• Our convention – end each pointer variable name with Ptr

• Other common naming conventions include starting the variable


name with p (e.g., pCount) or p_ (e.g., p_count)

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.2 Pointer Variable Definitions and
Initialization (3 of 3)
Define Variables in Separate Statements
• The * does not distribute to each variable:
– int *countPtr, count;
– countPtr is a pointer to int, but count is just an int
• Always write the preceding declaration as two statements to prevent ambiguity:
– int *countPtr;
– int count;

Initializing and Assigning Values to Pointers


• Initialize pointers when they’re defined, or assign them a value
• A pointer may be initialized to NULL, 0 or an address:
– NULL points to nothing.
– 0 is equivalent to NULL. NULL is preferred.
– Assigning a variable’s address to a pointer is discussed in Section 7.3

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (1 of 6)
• Unary address operator (&) returns the address of its operand
• int y = 5;
• int *yPtr = &y;
– initializes pointer variable yPtr with variable y’s address
– yPtr is then said to “point to” y

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (2 of 6)
• The following diagram shows the preceding pointer’s
representation in memory, assuming that integer variable
y is stored at location 600000 and the pointer variable
yPtr is stored at location 500000

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (3 of 6)
• Unary indirection operator (*), also called the dereferencing
operator
• Apply to a pointer operand to get the value of the object to
which the pointer points—known as dereferencing a pointer
• yPtr points to y, which is 5, so the following statement prints 5
– printf("%d", *yPtr);
• Dereferencing a pointer that has not been initialized with or
assigned the address of another variable in memory is an error
– Can cause a fatal execution-time error, accidentally modify
data, produce incorrect results, or lead to a security breach

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (4 of 6)
• Figure 7.1 demonstrates the pointer operators & and *
• Conversion specification %p outputs a memory location
as a hexadecimal integer on most platforms
• The & and * operators are complements of one another
• The addresses in the output will vary across systems that
use different processor architectures, different compilers
and even different compiler settings

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (5 of 6)
1. // fig07_01.c
2. // Using the & and * pointer operators.
3. #include <stdio.h>
4.
5. int main(void) {
6. int a = 7;
7. int *aPtr = &a; // set aPtr to the address of a
8.
9. printf("Address of a is %p\nValue of aPtr is %p\n\n", &a,
aPtr);
10. printf("Value of a is %d\nValue of *aPtr is %d\n\n", a,
*aPtr);
11. printf("Showing that * and & are complements of each
other\n");
12. printf("&*aPtr = %p\n*&aPtr = %p\n", &*aPtr, *&aPtr);
13. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.3 Pointer Operators (6 of 6)
Address of a is 0x7fffe69386cc
Value of aPtr is 0x7fffe69386cc

Value of a is 7
Value of *aPtr is 7

Showing that * and & are complements of each other


&*aPtr = 0x7fffe69386cc
*&aPtr = 0x7fffe69386cc

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (1 of 18)
• By default, arguments (other than arrays) are passed by value

• Functions often need to modify variables in the caller or to receive a pointer


to a large object to avoid the overhead of copying it (as in pass-by-value)
• A return statement can return at most one value from a called function to
its caller—pass-by-reference can enable a function to “return” multiple
values by modifying the caller’s variables

• Pointers and the indirection operator enable pass-by-reference

• When calling a function with arguments that should be modified in the


caller, you use & to pass each variable’s address

• A function that receives the address of a variable in the caller can use the
indirection operator (*) to modify the value at that location in the caller’s
memory, thus effecting pass-by-reference

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (2 of 18)
Pass-By-Value
• Line 11 of Fig 7.2 passes the variable number by value
ur e

to function cubeByValue (lines 16–18), which cubes its


argument and returns the new value
• Line 11 assigns the new value to number in main,
replacing number’s value

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (3 of 18)
1. // fig07_02.c
2. // Cube a variable using pass-by-value.
3. #include <stdio.h>
4.
5. int cubeByValue(int n); // prototype
6.
7. int main(void) {
8. int number = 5; // initialize number
9.
10. printf("The original value of number is %d", number);
11. number = cubeByValue(number); // pass number by value to
cubeByValue
12. printf("\nThe new value of number is %d\n", number);
13. }
14.
15. // calculate and return cube of integer argument
16. int cubeByValue(int n) {
17. return n * n * n; // cube local variable n and return result
18. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.4 Passing Arguments to Functions by
Reference (4 of 18)
The original value of number is 5
The new value of number is 125

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (5 of 18)
• Line 12 of Fig 7.3 passes the variable number’s address to function
ur e

cubeByReference (lines 17–19)

• Passing the address enables pass-by-reference


• The function’s parameter is a pointer to an int called nPtr (line 17).
• The expression *nPtr dereferences the pointer
• The function assigns the calculation result to *nPtr—which is really
the variable number in main—thus changing number’s value in main
• Use pass-by-value unless the caller explicitly requires the called
function to modify the argument variable’s value in the caller
– Prevents accidental modification of the caller’s arguments and is
another example of the principle of least privilege

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (6 of 18)
1. // fig07_03.c
2. // Cube a variable using pass-by-reference with a pointer
argument.
3.
4. #include <stdio.h>
5.
6. void cubeByReference(int *nPtr); // function prototype
7.
8. int main(void) {
9. int number = 5; // initialize number
10.
11. printf("The original value of number is %d", number);
12. cubeByReference(&number); // pass address of number to
cubeByReference
13. printf("\nThe new value of number is %d\n", number);
14. }
15.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.4 Passing Arguments to Functions by
Reference (7 of 18)
16. // calculate cube of *nPtr; actually modifies number in main
17. void cubeByReference(int *nPtr) {
18. *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr
19. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (8 of 18)
The original value of number is 5
The new value of number is 125

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (9 of 18)
Use a Pointer Parameter to Receive an Address
• A function receiving an address must use a pointer parameter
– void cubeByReference(int *nPtr) {

Pointer Parameters in Function Prototypes


• The function prototype for cubeByReference (Fig 7.3, line 6) ur e

specifies an int * parameter


• It’s not necessary to include pointer names in function prototype
– They’re ignored by the compiler
– But it’s good practice to include them for documentation
purposes

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (10 of 18)
Functions That Receive One-Dimensional Arrays
• The compiler does not differentiate between a function
that receives a pointer and one that receives a one-
dimensional array
• The function must “know” when it’s receiving an array
versus. a single variable passed by reference
• A parameter of the form int b[] is converted to int *b
• The two forms are interchangeable

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (11 of 18)
Pass-By-Value Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (12 of 18)
Pass-By-Value Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (13 of 18)
Pass-By-Value Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (14 of 18)
Pass-By-Value Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (15 of 18)
Pass-By-Value Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (16 of 18)
Pass-By-Reference Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (17 of 18)
Pass-By-Reference Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.4 Passing Arguments to Functions by
Reference (18 of 18)
Pass-By-Reference Step-By-Step

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5 Using the const Qualifier with
Pointers
• const qualifier informs compiler that a variable should not be modified
– Enforces the principle of least privilege
– Reduces debugging time and prevents unintentional side effects

• Four ways to pass to a function a pointer to data:


– a non-constant pointer to non-constant data.
– a constant pointer to non-constant data.
– a non-constant pointer to constant data.
– a constant pointer to constant data.

• Each provides different access privileges

• How do you choose?


– Let the principle of least privilege be your guide
– Always award a function enough access to the data in its parameters to
accomplish its specified task, but absolutely no more

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.1 Converting a String to Uppercase Using a
Non-Constant Pointer to Non-Constant Data (1 of 3)

• Highest level of data access — non-constant pointer to


non-constant data
• Data can be modified through the dereferenced pointer
• The pointer can be modified to point to other data items
• A function might use such a pointer to receive a string
argument, then process (and possibly modify) each
character in the string
• Function convertToUppercase in Fig 7.6 declares itsur e

parameter this way and uses it to convert lowercase


characters to uppercase
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.5.1 Converting a String to Uppercase Using a
Non-Constant Pointer to Non-Constant Data (2 of 3)

1. // fig07_06.c
2. // Converting a string to uppercase using a
3. // non-constant pointer to non-constant data.
4. #include <ctype.h>
5. #include <stdio.h>
6.
7. void convertToUppercase(char *sPtr); // prototype
8.
9. int main(void) {
10. char string[] = "cHaRaCters and $32.98"; // initialize
char array
11.
12. printf("The string before conversion is: %s\n", string);
13. convertToUppercase(string);
14. printf("The string after conversion is: %s\n", string);
15. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.1 Converting a String to Uppercase Using a
Non-Constant Pointer to Non-Constant Data (3 of 3)

16.
17. // convert string to uppercase letters
18. void convertToUppercase(char *sPtr) {
19. while (*sPtr != '\0') { // current character is not
'\0'
20. *sPtr = toupper(*sPtr); // convert to uppercase
21. ++sPtr; // make sPtr point to the next character
22. }
23. }

Output:
The string before conversion is: cHaRaCters and $32.98
The string after conversion is: CHARACTERS AND $32.98

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (1 of 7)

• Non-constant pointer to constant data can be modified


to point to any data item of the appropriate type, but the
data to which it points cannot be modified
• A function might receive such a pointer to process an array
argument’s elements without modifying them
• Function printCharacters (Fig 7.7) outputs each
ur e

character in a string until it encounters a null character


• After displaying each character, the loop increments
pointer sPtr to point to the string’s next character

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (2 of 7)

1. // fig07_07.c
2. // Printing a string one character at a time using
3. // a non-constant pointer to constant data.
4.
5. #include <stdio.h>
6.
7. void printCharacters(const char *sPtr);
8.
9. int main(void) {
10. // initialize char array
11. char string[] = "print characters of a string";
12.
13. puts("The string is:");
14. printCharacters(string);
15. puts("");
16. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (3 of 7)

17.
18. // sPtr cannot be used to modify the character to which
it points,
19. // i.e., sPtr is a "read-only" pointer
20. void printCharacters(const char *sPtr) {
21. // loop through entire string
22. for (; *sPtr != '\0'; ++sPtr) { // no initialization
23. printf("%c", *sPtr);
24. }
25. }

Output:
The string is:
print characters of a string

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (4 of 7)

Trying to Modify Constant Data


• Figure 7.8 shows the Visual C++ errors from compiling a
function that receives a non-constant pointer to constant data
and tries to use it to modify the data
• The error message you receive is compiler-specific
– Xcode’s LLVM compiler reports the error:
▪ error: read-only variable is not
assignable
– GNU gcc compiler reports the error:
▪ error: assignment of read-only location
‘*xPtr’

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (5 of 7)

1. // fig07_08.c
2. // Attempting to modify data through a
3. // non-constant pointer to constant data.
4. #include <stdio.h>
5. void f(const int *xPtr); // prototype
6.
7. int main(void) {
8. int y = 7; // define y
9.
10. f(&y); // f attempts illegal modification
11. }
12.
13. // xPtr cannot be used to modify the
14. // value of the variable to which it points
15. void f(const int *xPtr) {
16. *xPtr = 100; // error: cannot modify a const object
17. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (6 of 7)

Error Output:
fig07_08.c(16,5): error C2166: l-value specifies const object

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.2 Printing a String One Character at a Time Using
a Non-Constant Pointer to Constant Data (7 of 7)

Passing Structures v s Arrays


er su

• Arrays are aggregate types

• Chapter 10 discusses another form of aggregate type called a structure


(sometimes called a record or tuple in other languages), which can store
related data items of the same or different types under one name

• Structures are passed by value

• Passing large objects such as structures by using pointers to constant data


obtains the performance of pass-by-reference and the security of pass-by-
value

• If memory is low and execution efficiency is a concern, use pointers. If memory


is in abundance and efficiency is not a major concern, pass data by value to
enforce the principle of least privilege

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.3 Attempting to Modify a Constant
Pointer to Non-Constant Data (1 of 3)
• A constant pointer to non-constant data always points to the
same location, but the data can be modified through the pointer
– Default for an array name, which is a constant pointer to the
array’s first element
• Can be used to receive an array as an argument to a function that
accesses array elements using array subscript notation
• Pointers declared const must be initialized when they’re defined
– Function parameters are initialized with arguments in a function
call
• Figure 7.9 attempts to modify a constant pointer
• ptr is defined in line 11 to be of type int * const, which is read
right-to-left as “ptr is a constant pointer to an integer”
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.5.3 Attempting to Modify a Constant
Pointer to Non-Constant Data (2 of 3)
1. // fig07_09.c
2. // Attempting to modify a constant pointer to non-constant
data.
3. #include <stdio.h>
4.
5. int main(void) {
6. int x = 0; // define x
7. int y = 0; // define y
8.
9. // ptr is a constant pointer to an integer that can be
modified
10. // through ptr, but ptr always points to the same memory
location
11. int * const ptr = &x;
12.
13. *ptr = 7; // allowed: *ptr is not const
14. ptr = &y; // error: ptr is const; cannot assign new address
15. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.3 Attempting to Modify a Constant
Pointer to Non-Constant Data (3 of 3)
Error Output:
fig07_09.c(14,4): error C2166: l-value specifies
const object

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.4 Attempting to Modify a Constant
Pointer to Constant Data (1 of 3)
• The least access privilege is granted by a constant pointer to
constant data
• Such a pointer always points to the same memory location, and the
data at that memory location cannot be modified
• This is how an array should be passed to a function that looks at the
elements using array subscript notation and does not modify them
• Figure 7.10 defines ptr (line 12) to be of type const int *const
– Read right-to-left as “ptr is a constant pointer to an integer
constant.”
• The output shows the error messages generated when we attempt to
modify the data to which ptr points (line 15) and when we attempt
to modify the address stored in the pointer variable (line 16)
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.5.4 Attempting to Modify a Constant
Pointer to Constant Data (2 of 3)
1. // fig07_10.c
2. // Attempting to modify a constant pointer to constant data.
3. #include <stdio.h>
4.
5. int main(void) {
6. int x = 5;
7. int y = 0;
8.
9. // ptr is a constant pointer to a constant integer. ptr
always
10. // points to the same location; the integer at that location
11. // cannot be modified
12. const int *const ptr = &x; // initialization is OK
13.
14. printf("%d\n", *ptr);
15. *ptr = 7; // error: *ptr is const; cannot assign new value
16. ptr = &y; // error: ptr is const; cannot assign new address
17. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.5.4 Attempting to Modify a Constant
Pointer to Constant Data (3 of 3)
• Error Output:
– fig07_10.c(15,5): error C2166: l-value specifies const object
– fig07_10.c(16,4): error C2166: l-value specifies const object

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (1 of 8)

• Let’s improve the bubble-sort program of Fig 6.12 to use ur e

two functions—bubbleSort and swap (Fig 7.11) ur e

• Function bubbleSort sorts the array


• It calls function swap (line 42) to exchange the array
elements array[j] and array[j + 1].

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (2 of 8)

1. // fig07_11.c
2. // Putting values into an array, sorting the values into
3. // ascending order and printing the resulting array.
4. #include <stdio.h>
5. #define SIZE 10
6.
7. void bubbleSort(int * const array, size_t size); // prototype
8.
9. int main(void) {
10. // initialize array a
11. int a[SIZE] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
12.
13. puts("Data items in original order");
14.
15. // loop through array a
16. for (size_t i = 0; i < SIZE; ++i) {
17. printf("%4d", a[i]);
18. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.6 Bubble Sort Using Pass-By-Reference (3 of 8)

19.
20. bubbleSort(a, SIZE); // sort the array
21.
22. puts("\nData items in ascending order");
23.
24. // loop through array a
25. for (size_t i = 0; i < SIZE; ++i) {
26. printf("%4d", a[i]);
27. }
28.
29. puts("");
30. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (4 of 8)

32. // sort an array of integers using bubble sort algorithm


33. void bubbleSort(int * const array, size_t size) {
34. void swap(int *element1Ptr, int *element2Ptr); // prototype
35.
36. // loop to control passes
37. for (int pass = 0; pass < size - 1; ++pass) {
38. // loop to control comparisons during each pass
39. for (size_t j = 0; j < size - 1; ++j) {
40. // swap adjacent elements if they’re out of order
41. if (array[j] > array[j + 1]) {
42. swap(&array[j], &array[j + 1]);
43. }
44. }
45. }
46. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (5 of 8)

47.
48. // swap values at memory locations to which element1Ptr and
49. // element2Ptr point
50. void swap(int *element1Ptr, int *element2Ptr) {
51. int hold = *element1Ptr;
52. *element1Ptr = *element2Ptr;
53. *element2Ptr = hold;
54. }

Output:
Data items in original order
2 6 4 8 10 12 89 68 45 37
Data items in ascending order
2 4 6 8 10 12 37 45 68 89

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (6 of 8)

Function swap
• C enforces information hiding between functions
– swap does not have access to individual array
elements in bubbleSort by default
• bubbleSort wants swap to modify individual elements,
so it passes each to swap by reference
– swap(&array[j], &array[j + 1]);
• swap uses the pointers it receives to exchange the
values at the two memory locations

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.6 Bubble Sort Using Pass-By-Reference (7 of 8)

Function bubbleSort’s Array Parameter


• The function header (line 33) declares its parameter as int *
const array rather than int array[]
– These notations are interchangeable; but array notation is
preferred for readability.

Function swap’s Prototype in Function bubbleSort’s Body


• The prototype for function swap (line 34) is included in
bubbleSort’s body because only bubbleSort calls swap
– Restricts proper swap calls to those made from
bubbleSort (or any function that appears after swap in
the source code)
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.6 Bubble Sort Using Pass-By-Reference (8 of 8)

Function bubbleSort’s size Parameter

• When an array is passed to a function, the memory address of the


array’s first element, of course, does not convey the number of array
elements
• Therefore, you must pass the array size to the function to know how
many elements to sort
• There are two main benefits to passing the array size to bubbleSort—
software reusability and proper software engineering
• By defining the function to receive the array size as an argument, we
enable the function to be used by any program that sorts one-
dimensional integer arrays of any size

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.7 sizeof Operator (1 of 8)
• Operator sizeof determines an object’s or type’s size in
bytes
• Applied at compilation time unless its operand is a
variable-length array (VLA; Section 6.12)
• When applied to an array’s name as in Fig 7.12 (line 12),
ur e

sizeof returns as a size_t value the array’s total


number of bytes
• sizeof is a compile-time operator, so it does not incur
any execution-time overhead (except for VLAs).

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.7 sizeof Operator (2 of 8)
1. // fig07_12.c
2. // Applying sizeof to an array name returns
3. // the number of bytes in the array.
4. #include <stdio.h>
5. #define SIZE 20
6.
7. size_t getSize(const float *ptr); // prototype
8.
9. int main(void){
10. float array[SIZE]; // create array
11.
12. printf("Number of bytes in the array is %zu\n",
sizeof(array));
13. printf("Number of bytes returned by getSize is %zu\n",
getSize(array));
14. }
15.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.7 sizeof Operator (3 of 8)
16. // return size of ptr
17. size_t getSize(const float *ptr) {
18. return sizeof(ptr);
19. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.7 sizeof Operator (4 of 8)
Output:
Number of bytes in the array is 80
Number of bytes returned by getSize is 8

• Even though function getSize receives an array of 20


elements as an argument, the function’s parameter ptr is
simply a pointer to the array’s first element. When you use
sizeof with a pointer, it returns the pointer’s size, not
the size of the item to which it points

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.7 sizeof Operator (5 of 8)
Determining the Sizes of the Standard Types, an Array
and a Pointer
• Figure 7.13 calculates the number of bytes used to store
each of the standard types
• The results of this program are implementation
dependent
• Often differ across platforms and sometimes across
different compilers on the same platform
• The output shows the results from our macOS system
using the Apple Xcode C++ compiler
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.7 sizeof Operator (6 of 8)
1. // fig07_13.c
2. // Using operator sizeof to determine standard type sizes.
3. #include <stdio.h>
4.
5. int main(void) {
6. char c = '\0';
7. short s = 0;
8. int i = 0;
9. long l = 0;
10. long long ll = 0;
11. float f = 0.0F;
12. double d = 0.0;
13. long double ld = 0.0;
14. int array[20] = {0}; // create array of 20 int elements
15. int *ptr = array; // create pointer to array
16.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.7 sizeof Operator (7 of 8)
17. printf(" sizeof c = %2zu\t sizeof(char) = %2zu\n",
18. sizeof c, sizeof(char));
19. printf(" sizeof s = %2zu\t sizeof(short) = %2zu\n",
20. sizeof s, sizeof(short));
21. printf(" sizeof i = %2zu\t sizeof(int) = %2zu\n",
22. sizeof i, sizeof(int));
23. printf(" sizeof l = %2zu\t sizeof(long) = %2zu\n",
24. sizeof l, sizeof(long));
25. printf(" sizeof ll = %2zu\t sizeof(long long) = %2zu\n",
26. sizeof ll, sizeof(long long));
27. printf(" sizeof f = %2zu\t sizeof(float) = %2zu\n",
28. sizeof f, sizeof(float));
29. printf(" sizeof d = %2zu\t sizeof(double) = %2zu\n",
30. sizeof d, sizeof(double));
31. printf(" sizeof ld = %2zu\tsizeof(long double) = %2zu\n",
32. sizeof ld, sizeof(long double));
33. printf("sizeof array = %2zu\n sizeof ptr = %2zu\n",
34. sizeof array, sizeof ptr);
35. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.7 sizeof Operator (8 of 8)
sizeof c = 1 sizeof(char) = 1
sizeof s = 2 sizeof(short) = 2
sizeof i = 4 sizeof(int) = 4
sizeof l = 8 sizeof(long) = 8
sizeof ll = 8 sizeof(long long) = 8
sizeof f = 4 sizeof(float) = 4
sizeof d = 8 sizeof(double) = 8
sizeof ld = 16 sizeof(long double) = 16
Blank

sizeof array = 80
Blank

sizeof ptr = 8

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8 Pointer Expressions and Pointer
Arithmetic
• Pointers are valid operands in arithmetic expressions,
assignment expressions and comparison expressions
• Not all arithmetic operators are valid with pointer
variables
• This section describes the operators that can have
pointers as operands, and how these operators are used

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.1 Pointer Arithmetic Operators
• The following arithmetic operations are allowed for pointers:
– incrementing (++) or decrementing ( − −),

– adding an integer to a pointer (+ or +=),

– subtracting an integer from a pointer ( − or − = ), and

– subtracting one pointer from another—meaningful only


when both pointers point into the same array.

• Pointer arithmetic on pointers that do not refer to array


elements is a logic error.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.2 Aiming a Pointer at an Array
• Assume int v[5] is defined,
and its first element is at
location 3000
• Assume vPtr points to v[0]
• The following diagram illustrates
this scenario for a machine with
four-byte integers
• vPtr can be initialized to point
to v with either of the statements
– vPtr = v;
– vPtr = &v[0];

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.3 Adding an Integer to a Pointer
• In arithmetic, 3000 + 2 yields the
value 3002
– Normally not the case with
pointer arithmetic
• Adding an integer to or
subtracting one from a pointer
increments or decrements by
that integer times the size of
the object to which the pointer
refers
• The diagram shows result of
vPtr += 2; for 4-byte objects

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.4 Subtracting an Integer From a
Pointer
• If vPtr contains 3016 (v[4]), the following statement
would set vPtr back to 3000 (v[0])—the beginning of
the array.
– vPtr −= 4;
• Using pointer arithmetic to adjust pointers to point outside
an array’s bounds is a logic error that could lead to
security problems.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.5 Incrementing and Decrementing a
Pointer
• To increment or decrement a pointer by one, use the
increment (++) and decrement ( − −) operators
– ++vPtr;
– vPtr++;
– −−vPtr;
– vPtr−−;

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.6 Subtracting One Pointer From
Another
• If vPtr contains the location 3000 and v2Ptr contains
the address 3008, the following statement assigns to x
the number of array elements between vPtr and
v2Ptr, in this case, 2 (not 8).
– x = v2Ptr - vPtr;
• Pointer arithmetic is undefined unless performed on
elements of the same array
• We cannot assume that two variables of the same type
are stored side-by-side in memory unless they’re
adjacent elements of an array

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.7 Assigning Pointers to One Another
• Pointers of the same type may be assigned to one
another
• This rule’s exception is a pointer to void (i.e., void *)—
a generic pointer that can represent any pointer type
• All pointer types can be assigned to a void *, and a
void * can be assigned a pointer of any type (including
another void *)
• A cast operation is not required

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.8 Pointer to void
• A pointer to void cannot be dereferenced
• A void * contains a memory location for an unknown
type
– Number of bytes to which the pointer refers is not
known
• The compiler must know the type to determine the
number of bytes that represent the referenced value
• Dereferencing a void * pointer is a syntax error

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.8.9 Comparing Pointers
• You can compare pointers using equality and relational
operators
• Meaningful only if the pointers point to elements of the
same array
• Otherwise, such comparisons are logic errors
• A common use of pointer comparison is determining
whether a pointer is NULL

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9 Relationship Between Pointers and
Arrays
• Arrays and pointers often may be used interchangeably
• Think of an array name as a constant pointer to the first element
• Pointers can be used to do any operation involving array subscripting
• int b[5];
int *bPtr;
– The array name b is a pointer to the array’s first element
– Can set bPtr to the address of the array b’s first element with
the statement:
▪ bPtr = b;
– Equivalent to taking the address of array b’s first element:
▪ bPtr = &b[0];

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.1 Pointer/Offset Notation
• b[3] can alternatively be referenced with the pointer
expression
– *(bPtr + 3)
• The 3 in the expression is the offset to the pointer
• When bPtr points to the array’s first element, the offset
indicates which array element to reference
– Offset’s value is identical to the array subscript
• Referred to as pointer/offset notation
• Parentheses are required because the precedence of * is
higher than that of +
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.9.2 Pointer/Subscript Notation
• Pointers can be subscripted like arrays
• If bPtr has the value b, the following expression refers to
the array element b[1]
– bPtr[1]
• Referred to as pointer/subscript notation.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.3 Cannot Modify an Array Name with
Pointer Arithmetic
• An array name always points to the beginning of the array
• It’s like a constant pointer
• b += 3
– is invalid because it attempts to modify the array
name’s value with pointer arithmetic
• Attempting to modify the value of an array name with
pointer arithmetic is a compilation error.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (1 of 6)
• Figure 7.14 uses the four methods we’ve discussed for
referring to array elements to print the four elements of
the integer array b
– array subscripting
– pointer/offset with the array name as a pointer
– pointer subscripting
– pointer/offset with a pointer

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (2 of 6)
1. // fig07_14.cpp
2. // Using subscripting and pointer notations with arrays.
3. #include <stdio.h>
4. #define ARRAY_SIZE 4
5.
6. int main(void) {
7. int b[] = {10, 20, 30, 40}; // create and initialize array b
8. int *bPtr = b; // create bPtr and point it to array b
9.
10. // output array b using array subscript notation
11. puts("Array b printed with:\nArray subscript notation");
12.
13. // loop through array b
14. for (size_t i = 0; i < ARRAY_SIZE; ++i) {
15. printf("b[%zu] = %d\n", i, b[i]);
16. }
17.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (3 of 6)
18. // output array b using array name and pointer/offset notation
19. puts("\nPointer/offset notation where the pointer is the
array name");
20.
21. // loop through array b
22. for (size_t offset = 0; offset < ARRAY_SIZE; ++offset) {
23. printf("*(b + %zu) = %d\n", offset, *(b + offset));
24. }
25.
26. // output array b using bPtr and array subscript notation
27. puts("\nPointer subscript notation");
28.
29. // loop through array b
30. for (size_t i = 0; i < ARRAY_SIZE; ++i) {
31. printf("bPtr[%zu] = %d\n", i, bPtr[i]);
32. }
33.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (4 of 6)
34. // output array b using bPtr and pointer/offset notation
35. puts("\nPointer/offset notation");
36.
37. // loop through array b
38. for (size_t offset = 0; offset < ARRAY_SIZE; ++offset) {
39. printf("*(bPtr + %zu) = %d\n", offset, *(bPtr + offset));
40. }
41. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (5 of 6)
Array b printed with:
Array subscript notation

b[0] = 10
b[1] = 20
b[2] = 30
b[3] = 40

Pointer/offset notation where the pointer is the array name

*(b + 0) = 10
*(b + 1) = 20
*(b + 2) = 30
*(b + 3) = 40

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.4 Demonstrating Pointer Subscripting
and Offsets (6 of 6)
Pointer subscript notation
bPtr[0] = 10
bPtr[1] = 20
bPtr[2] = 30
bPtr[3] = 40

Pointer/offset notation
*(bPtr + 0) = 10
*(bPtr + 1) = 20
*(bPtr + 2) = 30
*(bPtr + 3) = 40

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (1 of 7)
• To further illustrate array and pointer interchangeability,
let’s look at two string-copying functions—copy1 and
copy2—in Fig 7.15
ur e

• Both functions copy a string into a character array, but


they’re implemented differently

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (2 of 7)
1. // fig07_15.c
2. // Copying a string using array notation and pointer
notation.
3. #include <stdio.h>
4. #define SIZE 10
5.
6. void copy1(char * const s1, const char * const s2); //
prototype
7. void copy2(char *s1, const char *s2); // prototype
8.
9. int main(void) {
10. char string1[SIZE]; // create array string1
11. char *string2 = "Hello"; // create a pointer to a string
12.
13. copy1(string1, string2);
14. printf("string1 = %s\n", string1);

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (3 of 7)
15.
16. char string3[SIZE]; // create array string3
17. char string4[] = "Good Bye"; // create an array containing
a string
18.
19. copy2(string3, string4);
20. printf("string3 = %s\n", string3);
21. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (4 of 7)
22.
23.// copy s2 to s1 using array notation
24.void copy1(char * const s1, const char * const s2) {
25. // loop through strings
26. for (size_t i = 0; (s1[i] = s2[i]) != '\0'; ++i) {
27. ; // do nothing in body
28. }
29.}
30.
31.// copy s2 to s1 using pointer notation
32.void copy2(char *s1, const char *s2) {
33. // loop through strings
34. for (; (*s1 = *s2) != '\0'; ++s1, ++s2) {
35. ; // do nothing in body
36. }
37.}

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (5 of 7)
string1 = Hello
string3 = Good Bye

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.9.5 String Copying with Arrays and
Pointers (6 of 7)
Copying with Array Subscript Notation
• copy1 uses array subscript notation to copy the string in s2 to the character array s1.
• The expression s1[i] = s2[i] copies one character from s2 to s1
• When the null character is encountered in s2, it’s assigned to s1
– Since the assignment’s value is what gets assigned to the left operand (s1), the loop
terminates when an element of s1 receives the null character, which has the value 0
(false)

Copying with Pointers and Pointer Arithmetic


• copy2 uses pointers and pointer arithmetic to copy s2 to the character array s1
• *s1 = *s2 performs the copy by dereferencing s2 and assigning that character to
the location s1
• After the assignment, line 34 increments s1 and s2 to point to each string’s next
character
• When the assignment copies the null character into s1, the loop terminates.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.9.5 String Copying with Arrays and
Pointers (7 of 7)
Notes Regarding Functions copy1 and copy2
• The first argument to both copy1 and copy2 must be an
array large enough to hold the second argument’s string
– Otherwise, a logic error may occur when an attempt is
made to write into a memory location that’s not part of the
array
• In both functions, the second argument is copied into the first
argument—characters are read from it one at a time, but the
characters are never modified
– The second parameter is declared to point to a constant
so that the principle of least privilege is enforced

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.10 Arrays of Pointers (1 of 2)
• Arrays may contain pointers
– Commonly for array of strings, referred to simply as a string array

• Each element in a C string is essentially a pointer to its first character


• const char *suit[4] = {"Hearts", "Diamonds", "Clubs",
"Spades"};
– The char * indicates that each suit element is of type “pointer to char.”
– const indicates that the string each element points to cannot be modified
– "Hearts", "Diamonds", "Clubs" and "Spades" are placed into the array
– Each is stored in memory as a null-terminated character string that’s
one character longer than the number of characters in the quotes

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.10 Arrays of Pointers (2 of 2)
• Only pointers are actually stored in the array, as shown in
the following diagram

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (1 of 17)

• Let’s use random number generation to develop a card shuffling


and dealing simulation program, which can then be used to
implement programs that play card games
• To reveal some subtle performance problems, we’ve
intentionally used suboptimal shuffling and dealing algorithms
– In this chapter’s exercises and in Chapter 10, we develop
more efficient algorithms.
• Using the top-down, stepwise refinement approach, we develop
a program that will shuffle a deck of 52 playing cards, then deal
each card
– The top-down approach is particularly useful in attacking
more complex problems than you’ve seen in earlier chapters
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (2 of 17)

Representing a Deck of Cards as


a Two-Dimensional Array

• 4-by-13 two-dimensional array


deck represenst the deck of
playing cards

• rows correspond to the suits

• columns correspond to the


faces
• We’ll load string array suit with
character strings representing
the four suits, and load string
array face with character strings
representing the 13 face values

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (3 of 17)

Shuffling the Two-Dimensional Array

• First, set all elements of deck to 0

• Then, choose a row (0–3) and a column (0–12) at random


• Place the number 1 in array element deck[row][column] to indicate that
this card will be the first one dealt from the shuffled deck
• Repeat this process for the numbers 2, 3, …, 52, randomly inserting each in
the deck array to indicate which cards are to be dealt second, third, …, and
fifty-second in the shuffled deck

• As the deck array begins to fill with card numbers, a card may be selected
again
– Ignore and choose other random row and column values repeatedly until
you find an unselected card

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (4 of 17)

Possibility of Indefinite Postponement


• This shuffling algorithm can execute indefinitely if cards that have
already been shuffled are repeatedly selected at random—known as
indefinite postponement
– The exercises discuss a better shuffling algorithm
– Seek algorithms that avoid indefinite postponement.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (5 of 17)

Dealing Cards from the Two-Dimensional Array


• To deal the first card, search the array for
deck[row][column] equal to 1 using nested for statements
• What card does that element of the array correspond to?
– The suit array has been preloaded with the four suits, so to
get the card’s suit, we print the character string suit[row]
– Similarly, to get the card’s face, we print the character string
face[column].
• We also print the character string " of ", as in "King of Clubs",
"Ace of Diamonds" and so on

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (6 of 17)

Developing the Program’s Logic with Top-Down,


Stepwise Refinement
• top
– Shuffle and deal 52 cards
• first refinement yields:
– Initialize the suit array
Initialize the face array
Initialize the deck array
Shuffle the deck
Deal 52 cards

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (7 of 17)

Developing the Program’s Logic with Top-Down,


Stepwise Refinement
• “Shuffle the deck” may be refined as follows:
– For each of the 52 cards
Place card number in a randomly selected unoccupied
element of deck

• “Deal 52 cards” may be refined as follows:


– For each of the 52 cards
Find the card number in the deck array and print its
face and suit
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (8 of 17)

Developing the Program’s Logic with Top-Down, Stepwise


Refinement
• The complete second refinement is:
– Initialize the suit array
Initialize the face array
Initialize the deck array

– For each of the 52 cards


Place card number in a randomly selected unoccupied slot of deck

– For each of the 52 cards


Find the card number in the deck array and print the card’s
face and suit
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (9 of 17)

Developing the Program’s Logic with Top-Down, Stepwise


Refinement
• “Place card number in randomly selected unoccupied slot of deck”
may be refined as:
– Choose slot of deck randomly
– While chosen slot of deck has been previously chosen
Choose slot of deck randomly
– Place card number in chosen slot of deck
• “Find the card number in the deck array and print its face and suit”
may be refined as:
– For each slot of the deck array
If slot contains card number
Print the card’s face and suit
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (10 of 17)
Developing the Program’s Logic with Top-Down, Stepwise Refinement
• Incorporating these expansions yields our third refinement:
– Initialize the suit array
Initialize the face array
Initialize the deck array
– For each of the 52 cards
Choose slot of deck randomly
While slot of deck has been previously chosen
Choose slot of deck randomly
Place card number in chosen slot of deck

– For each of the 52 cards


For each slot of deck array
If slot contains desired card number
Print the card’s face and suit

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (11 of 17)

Implementing the Card Shuffling and Dealing Program


• The card shuffling and dealing program and a sample
execution are shown in Fig 7.16.
ur e

• Conversion specification %s prints a pointer to char that


points to a string or a char array that contains a string
• Line 59’s format specification displays the card’s face
right-aligned in a field of five characters followed by " of
" and the card’s suit left-aligned in a field of eight
characters

– The minus sign in %-8s indicates left-alignment


Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (12 of 17)
1. // fig07_16.c
2. // Card shuffling and dealing.
3. #include <stdio.h>
4. #include <stdlib.h>
5. #include <time.h>
6.
7. #define SUITS 4
8. #define FACES 13
9. #define CARDS 52
10.
11. // prototypes
12. void shuffle(int deck[][FACES]);
13. void deal(int deck[][FACES], const char *face[], const char
*suit[]);
14.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (13 of 17)
15. int main(void) {
16. // initialize deck array
17. int deck[SUITS][FACES] = {0};
18.
19. srand(time(NULL)); // seed random-number generator
20. shuffle(deck); // shuffle the deck
21.
22. // initialize suit array
23. const char *suit[SUITS] = {"Hearts", "Diamonds", "Clubs",
"Spades"};
24.
25. // initialize face array
26. const char *face[FACES] = {"Ace", "Deuce", "Three", "Four",
"Five",
27. "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen",
"King"};
28.
29. deal(deck, face, suit); // deal the deck
30. }
31.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (14 of 17)
32. // shuffle cards in deck
33. void shuffle(int deck[][FACES]) {
34. // for each of the cards, choose slot of deck randomly
35. for (size_t card = 1; card <= CARDS; ++card) {
36. size_t row = 0; // row number
37. size_t column = 0; // column number
38.
39. // choose new random location until unoccupied slot found
40. do {
41. row = rand() % SUITS;
42. column = rand() % FACES;
43. } while(deck[row][column] != 0);
44.
45. deck[row][column] = card; // place card number in chosen
slot
46. }
47. }
48.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (15 of 17)
49. // deal cards in deck
50. void deal(int deck[][FACES], const char *face[], const char
*suit[]) {
51. // deal each of the cards
52. for (size_t card = 1; card <= CARDS; ++card) {
53. // loop through rows of deck
54. for (size_t row = 0; row < SUITS; ++row) {
55. // loop through columns of deck for current row
56. for (size_t column = 0; column < FACES; ++column) {
57. // if slot contains current card, display card
58. if (deck[row][column] == card) {
59. printf("%5s of %-8s %c", face[column], suit[row],
60. card % 4 == 0 ? '\n' : '\0'); // 2-column
format
61. }
62. }
63. }
64. }
65. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (16 of 17)
Ace of Hearts Jack of Hearts Five of Clubs King of Clubs
Eight of Diamonds Three of Clubs Deuce of Hearts Four of Hearts
Ace of Clubs Deuce of Spades Queen of Diamonds Six of Hearts
Seven of Clubs Five of Hearts Deuce of Clubs King of Hearts
Nine of Spades Ace of Spades Ace of Diamonds Eight of Spades
Eight of Hearts Ten of Spades Ten of Hearts Queen of Clubs
Jack of Spades Jack of Diamonds Three of Spades Four of Clubs
Four of Spades Ten of Clubs King of Diamonds Six of Spades
Nine of Clubs Six of Diamonds Queen of Spades King of Spades
Four of Diamonds Eight of Clubs Jack of Clubs Seven of Hearts
Seven of Diamonds Three of Hearts Five of Spades Nine of Hearts
Nine of Diamonds Three of Diamonds Deuce of Diamonds Queen of Hearts
Six of Clubs Seven of Spades Five of Diamonds Ten of Diamonds

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.11 Random-Number Simulation Case Study:
Card Shuffling and Dealing (17 of 17)

Improving the Dealing Algorithm


• There’s a weakness in the dealing algorithm
• Once a match is found, the two inner for statements continue searching
deck’s remaining elements
• We correct this deficiency in the exercises and in a Chapter 10 case study.

Related Exercises
• Exercise 7.12 (Card Shuffling and Dealing: Dealing Poker Hands)
• Exercise 7.13 (Project: Card Shuffling and Dealing—Which Poker Hand is
Better?)
• Exercise 7.14 (Project: Card Shuffling and Dealing—Simulating the Dealer)
• Exercise 7.15 (Project: Card Shuffling and Dealing—Allowing Players to Draw
Cards)
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.12 Function Pointers
• A function’s name is really the starting address in memory
of the code that performs the function’s task
• A pointer to a function contains the address of the
function in memory
• Pointers to functions can be passed to functions, returned
from functions, stored in arrays, assigned to other function
pointers of the same type and compared with one another
for equality or inequality

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (1 of 9)
• To demonstrate pointers to functions, Fig 7.17 presents a modified
ur e

version of Fig 7.11’s bubble-sort program


ur e

• The new version consists of main and functions bubbleSort, swap,


ascending and descending.
• Function bubbleSort receives a pointer to a function as an
argument—either function ascending or function descending—in
addition to an int array and the array’s size

• The user chooses whether to sort the array in ascending (1) or


descending (2) order.
– If the user enters 1, main passes ascending to bubbleSort
– If the user enters 2, main passes descending to bubbleSort

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (2 of 9)
1. // fig07_17.c
2. // Multipurpose sorting program using function pointers.
3. #include <stdio.h>
4. #define SIZE 10
5.
6. // prototypes
7. void bubbleSort(int work[], size_t size, int (*compare)(int a,
int b));
8. int ascending(int a, int b);
9. int descending(int a, int b);

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (3 of 9)
10.
11. int main(void) {
12. // initialize unordered array a
13. int a[SIZE] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
14.
15. printf("%s", "Enter 1 to sort in ascending order,\n"
16. "Enter 2 to sort in descending order: ");
17. int order = 0;
18. scanf("%d", &order
19. );

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (4 of 9)
20. puts("\nData items in original order");
21.
22. // output original array
23. for (size_t counter = 0; counter < SIZE; ++counter) {
24. printf("%5d", a[counter]);
25. }
26.
27. // sort array in ascending order; pass function ascending
as an
28. // argument to specify ascending sorting order
29. if (order == 1) {
30. bubbleSort(a, SIZE, ascending);
31. puts("\nData items in ascending order");
32. }
33. else { // pass function descending
34. bubbleSort(a, SIZE, descending);
35. puts("\nData items in descending order");
36. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (5 of 9)
37.
38. // output sorted array
39. for (size_t counter = 0; counter < SIZE; ++counter) {
40. printf("%5d", a[counter]);
41. }
42.
43. puts("\n");
44. }
45.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (6 of 9)
46. // multipurpose bubble sort; parameter compare is a pointer to
47. // the comparison function that determines sorting order
48. void bubbleSort(int work[], size_t size, int (*compare)(int a,
int b)) {
49. void swap(int *element1Ptr, int *element2ptr); // prototype
50.
51. // loop to control passes
52. for (int pass = 1; pass < size; ++pass) {
53. // loop to control number of comparisons per pass
54. for (size_t count = 0; count < size - 1; ++count) {
55. // if adjacent elements are out of order, swap them
56. if ((*compare)(work[count], work[count + 1])) {
57. swap(&work[count], &work[count + 1]);
58. }
59. }
60. }
61. }
62.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (7 of 9)
63. // swap values at memory locations to which element1Ptr and
64. // element2Ptr point
65. void swap(int *element1Ptr, int *element2Ptr) {
66. int hold = *element1Ptr;
67. *element1Ptr = *element2Ptr;
68. *element2Ptr = hold;
69. }
70.
71. // determine whether elements are out of order for an ascending
order sort
72. int ascending(int a, int b) {
73. return b < a; // should swap if b is less than a
74. }
75.
76. // determine whether elements are out of order for a descending
order sort
77. int descending(int a, int b) {
78. return b > a; // should swap if b is greater than a
79. }
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.12.1 Sorting in Ascending or
Descending Order (8 of 9)
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order: 1

Data items in original order


2 6 4 8 10 12 89 68 45 37
Data items in ascending order
2 4 6 8 10 12 37 45 68 89

Enter 1 to sort in ascending order,


Enter 2 to sort in descending order: 2

Data items in original order


2 6 4 8 10 12 89 68 45 37
Data items in descending order
89 68 45 37 12 10 8 6 4 2

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.1 Sorting in Ascending or
Descending Order (9 of 9)
Function Pointer Parameter
• int (*compare)(int a, int b)
– Tells bubbleSort to expect a parameter (compare) that’s a pointer to
a function, specifically for a function that receives two ints and returns
an int result
– The parentheses around *compare are required to group the * with
compare and indicate that compare is a pointer

• To call the function passed to bubbleSort via its function pointer, we


deference it (line 56)
– if ((*compare)(work[count], work[count + 1]))

• The call to the function could have been made as


– if (compare(work[count], work[count + 1]))
– Uses the pointer directly as the function name

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.2 Using Function Pointers to Create
a Menu-Driven System (1 of 5)
• A common use of function pointers is in menu-driven
systems
• A program prompts a user to select an option from a
menu (possibly from 0 to 2) by typing the menu item’s
number
• The program services each option with a different
function stored in an array of function pointers
• Figure 7.18 provides a generic example of the mechanics
of defining and using an array of function pointers

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.2 Using Function Pointers to Create
a Menu-Driven System (2 of 5)
1. // fig07_18.c
2. // Demonstrating an array of pointers to functions.
3. #include <stdio.h>
4.
5. // prototypes
6. void function1(int a);
7. void function2(int b);
8. void function3(int c);
9.
10. int main(void) {
11. // initialize array of 3 pointers to functions that each
take an
12. // int argument and return void
13. void (*f[3])(int) = {function1, function2, function3};
14.
15. printf("%s", "Enter a number between 0 and 2, 3 to end: ");
16. int choice = 0;
17. scanf("%d", &choice);
18.
Copyright © 2022 Pearson Education, Inc. All Rights Reserved
7.12.2 Using Function Pointers to Create
a Menu-Driven System (3 of 5)
19. // process user's choice
20. while (choice >= 0 && choice < 3) {
21. // invoke function at location choice in array f and pass
22. // choice as an argument
23. (*f[choice])(choice);
24.
25. printf("%s", "Enter a number between 0 and 2, 3 to end:
");
26. scanf("%d", &choice);
27. }
28.
29. puts("Program execution completed.");
30. }
31.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.2 Using Function Pointers to Create
a Menu-Driven System (4 of 5)
32. void function1(int a) {
33. printf("You entered %d so function1 was called\n\n", a);
34. }
35.
36. void function2(int b) {
37. printf("You entered %d so function2 was called\n\n", b);
38. }
39.
40. void function3(int c) {
41. printf("You entered %d so function3 was called\n\n", c);
42. }

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


7.12.2 Using Function Pointers to Create
a Menu-Driven System (5 of 5)
Enter a number between 0 and 2, 3 to end: 0
You entered 0 so function1 was called

Enter a number between 0 and 2, 3 to end: 1


You entered 1 so function2 was called

Enter a number between 0 and 2, 3 to end: 2


You entered 2 so function3 was called

Enter a number between 0 and 2, 3 to end: 3


Program execution completed.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved


Copyright

This work is protected by United States copyright laws and is


provided solely for the use of instructors in teaching their
courses and assessing student learning. Dissemination or sale of
any part of this work (including on the World Wide Web) will
destroy the integrity of the work and is not permitted. The work
and materials from it should never be made available to students
except by instructors using the accompanying text in their
classes. All recipients of this work are expected to abide by these
restrictions and to honor the intended pedagogical purposes and
the needs of other instructors who rely on these materials.

Copyright © 2022 Pearson Education, Inc. All Rights Reserved

You might also like