ilteris kaplan blog

Archive of blog posts since 2005

April 5, 2008

Wiki

Pointer Variable Declarations and Initialization

#wiki

Pointer Variable Declarations and Initialization

  • Pointer variables contain memory addresses as their values. Normally, a variable directly contains a specific value. However, a pointer contains the memory address of a variable that, in turn, contains a specific value. In this sense, a variable name directly references a value, and a pointer indirectly references a value. Referencing a value through a pointer is often called indirection.
  • Pointers, like any other variables, must be declared before they can be used. For example, the declaration

int *countPtr, count;

declares the variable countPtr to be of type int * (i.e., a pointer to an int value) and is read, “countPtr is a pointer to int” or “countPtr points to an object of type int.” Also, variable count in the preceding declaration is declared to be an int, not a pointer to an int. The * in the declaration applies only to countPtr. Each variable being declared as a pointer must be preceded by an asterisk (*). For example, the declaration


double *xPtr, *yPtr;

indicates that both xPtr and yPtr are pointers to double values. *Pointers should be initialized either when they are declared or in an assignment. A pointer may be initialized to 0, NULL or an address. A pointer with the value 0 or NULL points to nothing and is known as a null pointer. Symbolic constant NULL is defined in header file (and in several other standard library header files) to represent the value 0. Initializing a pointer to NULL is equivalent to initializing a pointer to 0, but in C++, 0 is used by convention. When 0 is assigned, it is converted to a pointer of the appropriate type. The value 0 is the only integer value that can be assigned directly to a pointer variable without casting the integer to a pointer type first.

Pointer Operators

  • The address operator (&) is a unary operator that returns the memory address of its operand. For example, assuming the declarations

int y = 5; // declare variable y
int *yPtr; // declare pointer variable yPtr

the statement


yPtr = &y; // assign address of y to yPtr

assigns the address of the variable y to pointer variable yPtr. Then variable yPtr is said to “point to” y. Now, yPtr indirectly references variable y’s value. Note that the use of the & in the preceding assignment statement is not the same as the use of the & in a reference variable declaration, which is always preceded by a data-type name.

  • The * operator, commonly referred to as the indirection operator or dereferencing operator, returns a synonym (i.e., an alias or a nickname) for the object to which its pointer operand points. For example, the statement

cout << *yPtr << endl;

prints the value of variable y, namely, 5, just as the statement


cout << y << endl;

would. Using * in this manner is called dereferencing a pointer. Note that a dereferenced pointer may also be used on the left side of an assignment statement, as in

*yPtr = 9;

which would assign 9 to y. The dereferenced pointer may also be used to receive an input value as in


cin >> *yPtr;

which places the input value in y.

Pointer operators & and *


 1  // 
 2  // Using the & and * operators.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 6
 7  int main()
 8  {
 9     int a; // a is an integer
10     int *aPtr; // aPtr is an int * -- pointer to an integer
11
12     a = 7; // assigned 7 to a
13     aPtr = &a; // assign the address of a to aPtr
14
15     cout << "The address of a is " << &a
16        << "\nThe value of aPtr is " << aPtr;
17     cout << "\n\nThe value of a is " << a
18        << "\nThe value of *aPtr is " << *aPtr;
19     cout << "\n\nShowing that * and & are inverses of "
20        << "each other.\n&*aPtr = " << &*aPtr
21        << "\n*&aPtr = " << *&aPtr << endl;
22     return 0; // indicates successful termination
23  } // end main

Passing Arguments to Functions by Reference with Pointers

  • There are three ways in C++ to pass arguments to a function; pass-by-value, pass-by-reference with reference arguments and pass-by-reference with pointer arguments.
  • Pointers, like references, also can be used to modify one or more variables in the caller or to pass pointers to large data objects to avoid the overhead of passing the objects by value.
  • In C++, programmers can use pointers and the indirection operator (*) to accomplish pass-by-reference (exactly as pass-by-reference is done in C programs, because C does not have references). When calling a function with an argument that should be modified, the address of the argument is passed. This is normally accomplished by applying the address operator (&) to the name of the variable whose value will be modified.
  • Arrays are not passed using operator &, because the name of the array is the starting location in memory of the array (i.e., an array name is already a pointer). The name of an array, arrayName, is equivalent to &arrayName[ 0 ]. When the address of a variable is passed to a function, the indirection operator (*) can be used in the function to form a synonym for the name of the variable. this in turn can be used to modify the value of the variable at that location in the caller’s memory.

Pass-by-value used to cube a variable’s value


 1   
 2  // Cube a variable using pass-by-value.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 6
 7  int cubeByValue( int ); // prototype
 8
 9  int main()
10  {
11     int number = 5;
12
13     cout << "The original value of number is " << number;
14
15     number = cubeByValue( number ); // pass number by value to cubeByValue
16     cout << "\nThe new value of number is " << number << endl;
17     return 0; // indicates successful termination
18  } // end main
19
20  // calculate and return cube of integer argument               
21  int cubeByValue( int n )                                       
22  {                                                              
23     return n * n * n; // cube local variable n and return result
24  } // end function cubeByValue                                  
  • Above example passes variable number by value to function cubeByValue (line 15). Function cubeByValue (lines 21-24) cubes its argument and passes the new value back to main using a return statement (line 23). The new value is assigned to number (line 15) in main. Note that the calling function has the opportunity to examine the result of the function call before modifying variable number’s value. For example, in this program, we could have stored the result of cubeByValue in another variable, examined its value and assigned the result to number only after determining that the returned value was reasonable.

Pass-by-reference with a pointer argument used to cube a variable’s value


1  // Fig. 8.7: fig08_07.cpp
 2  // Cube a variable using pass-by-reference with a pointer argument.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 6
 7  void cubeByReference( int * ); //   prototype
 8
 9  int main()
10  {
11     int number = 5;
12
13     cout << "The original value of number is " << number;
14
15     cubeByReference( &number ); // pass number address to cubeByReference
16
17     cout << "\nThe new value of number is " << number << endl;
18     return 0; // indicates successful termination
19  } // end main
20
21  // calculate cube of *nPtr; modifies variable number in main
22  void cubeByReference( int *nPtr )                           
23  {                                                           
24     *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr             
25  } // end function cubeByReference    
  • Above passes the variable number to function cubeByReference using pass-by-reference with a pointer argument (line 15)the address of number is passed to the function. Function cubeByReference (lines 22-25) specifies parameter nPtr (a pointer to int) to receive its argument. The function dereferences the pointer and cubes the value to which nPtr points (line 24). This directly changes the value of number in main.

Converting a string to uppercase



 1  // Fig. 8.10: fig08_10.cpp
 2  // Converting lowercase letters to uppercase letters
 3  // using a non-constant pointer to non-constant data.
 4  #include <iostream>
 5  using std::cout;
 6  using std::endl;
 7
 8  #include <cctype> // prototypes for islower and toupper
 9  using std::islower;
10  using std::toupper;
11
12  void convertToUppercase( char * );
13
14  int main()
15  {
16     char phrase[] = "characters and $32.98";
17
18     cout << "The phrase before conversion is: " << phrase;
19     convertToUppercase( phrase );
20     cout << "\nThe phrase after conversion is: " << phrase << endl;
21     return 0; // indicates successful termination
22  } // end main
23
24  // convert string to uppercase letters
25  void convertToUppercase( char *sPtr )
26  {
27     while ( *sPtr != '\0' ) // loop while current character is not '\0'
28     {
29        if ( islower( *sPtr ) ) // if character is lowercase,
30           *sPtr = toupper( *sPtr ); // convert to uppercase
31
32        sPtr++; // move sPtr to next character in string
33     } // end while
34  } // end function convertToUppercase

  • Function convertToUppercase (lines 25-34) declares parameter sPtr (line 25) to be a nonconstant pointer to nonconstant data (again, const is not used). The function processes one character at a time from the null-terminated string stored in character array phrase (lines 2733). Keep in mind that a character array’s name is really equivalent to a pointer to the first character of the array, so passing phrase as an argument to convertToUppercase is possible. Function islower (line 29) takes a character argument and returns true if the character is a lowercase letter and false otherwise. Characters in the range ‘a’ through ‘z’ are converted to their corresponding uppercase letters by function toupper (line 30); others remain unchangedfunction toupper takes one character as an argument. If the character is a lowercase letter, the corresponding uppercase letter is returned; otherwise, the original character is returned. Function toupper and function islower are part of the character-handling library . After processing one character, line 32 increments sPtr by 1 (this would not be possible if sPtr were declared const). When operator ++ is applied to a pointer that points to an array, the memory address stored in the pointer is modified to point to the next element of the array (in this case, the next character in the string). Adding one to a pointer is one valid operation in pointer arithmetic.

Continue Reading

Back to Archive