Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

01_Pointers_I

Download as pdf or txt
Download as pdf or txt
You are on page 1of 28

Pointers I

CEN116 Algorithms and Programming II


Introduction
• 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.
Pointer Variable Definitions and Initialization
• 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
Pointer Variable Definitions and Initialization
Pointer Variable Definitions and Initialization
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)
Pointer Variable Definitions and Initialization
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 next sections
Pointer Operators
• 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
Pointer Operators
• 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
Pointer Operators
• 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
Pointer Operators
• Next program 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
Pointer Operators
1.#include <stdio.h>
2.
3. int main(void) {
4. int a = 7;
5. int *aPtr = &a; // set aPtr to the address of a
6.
7. printf("Address of a is %p\nValue of aPtr is %p\n\n",
&a, aPtr);
8. printf("Value of a is %d\nValue of *aPtr is %d\n\n", a,
*aPtr);
9. printf("Showing that * and & are complements of each
other\n");
10. printf("&*aPtr = %p\n*&aPtr = %p\n", &*aPtr, *&aPtr);
11. }
Pointer Operators
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
Passing Arguments to Functions by Reference
• 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
Passing Arguments to Functions by Reference
1. // Cube a variable using pass-by-value.
2. #include <stdio.h>
3.
4. int cubeByValue(int n); // prototype
5.
6. int main(void) {
7. int number = 5; // initialize number
8.
9. printf("The original value of number is %d", number);
10. number = cubeByValue(number); // pass number by value to
cubeByValue
11. printf("\nThe new value of number is %d\n", number);
12. }
13.
14. // calculate and return cube of integer argument
15. int cubeByValue(int n) {
16. return n * n * n; // cube local variable n and return result
17. }
Passing Arguments to Functions by Reference
1. // Cube a variable using pass-by-reference with a pointer
argument.
2. #include <stdio.h>
3. void cubeByReference(int *nPtr); // function prototype
4.
5. int main(void) {
6. int number = 5; // initialize number
7. printf("The original value of number is %d", number);
8. cubeByReference(&number); // pass address of number to
cubeByReference
9. printf("\nThe new value of number is %d\n", number);
16. }
17. // calculate cube of *nPtr; actually modifies number in main
18. void cubeByReference(int *nPtr) {
19. *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr
20. }
Passing Arguments to Functions by Reference
• Passing the address enables pass-by-reference
• The function’s parameter is a pointer to an int called nPtr.
• 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
Passing Arguments to Functions by Reference
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 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
Passing Arguments to Functions by Reference
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
Bubble Sort Using Pass-by-Reference
• Let’s write a bubble sort program using two functions—bubbleSort
and swap.
• Function bubbleSort sorts the array.
• It calls function swap to exchange the array elements array[j] and
array[j + 1]
• Remember that C enforces information hiding between functions, so
swap does not have access to individual array elements in bubbleSort.
• Because bubbleSort wants swap to have access to the array elements
to be swapped, bubbleSort passes each of these elements by reference
to swap—the address of each array element is passed explicitly.
Bubble Sort Using Pass-by-Reference
• Although entire arrays are automatically passed by reference,
individual array elements are scalars and are ordinarily passed by
value.
• Therefore, bubbleSort uses the address operator (&) on each of the
array elements in the swap call to effect pass-by-reference as follows
• swap(&array[j], &array[j + 1]);
• Function swap receives &array[j] in pointer variable element1Ptr.
Bubble Sort Using Pass-by-Reference
• Even though swap—because of information hiding—is not allowed
to know the name array[j], swap may use *element1Ptr as a
synonym for array[j]—when swap references *element1Ptr,
it’s actually referencing array[j] in bubbleSort.
• Similarly, when swap references *element2Ptr, it’s actually
referencing array[j + 1] in bubbleSort
Bubble Sort Using Pass-by-Reference
• Even though swap is not allowed to say
int hold = array[j];
array[j] = array[j + 1];
array[j + 1] = hold;
precisely the same effect is achieved by
int hold = *element1Ptr;
*element1Ptr = *element2Ptr;
*element2Ptr = hold;
References
• C How to Program, Ninth Edition by Deitel & Deitel, Pearson, 2022.

You might also like