C++ Intro

Lecture 5: C++ pointers, function arguments, and references


String Literals


Consider


                    std::cout << "Hello";

The literal "Hello" is stored in memory as a sequence of bytes, terminated with the null character '\0' so that programs can find the end of the string. String literals said to be zero-terminated:

                    H  e  l  l  o  \0
                    

It is possible to create a variable to store the address of the first byte. For example,


                    char *pchar = "Hello";

Variable pchar stores physical address of the first character of the string, which is 'H' in our example.


Pointer


A pointer is a variable that contains the address of a variable.

Code that uses variables: Code that uses pointers to variables:

    int a = 5;
    int b = 10;
    int c;
    c = a + b;


    int* pa;          pa = &a;
    int* pb;          pb = &b;
    int* pc;          pc = &c;
    *pc = *pa + *pb;

The unary operator & gives the address of an object, so the statement

    pc = &c;
                    

assigns the physical address of variable c to the variable pc.

Please note that two uses of the asterisk * exist:

  1. Create pointer : the declaration of the pointer p appears as
    
        int* p;
    
    It is intended as a mnemonic to show that the expression p is a pointer to an integer variable.

  2. Access what my pointer points to: the unary operator *p is the indirection or dereferencing operator; when applied to a pointer, it accesses the object the pointer points to.

Pointers are variables


Pointers are variables, so they can be used without dereferencing:

    pb = pa;
    pc = pa;
                    

Pointer is constrained to point to a particular kind of object: every pointer points to a specific data type.


Pointers as function arguments



        void print( char* message )
        {
            std::cout << message;
        }

        int main()
        {
            print( "Hello" );
            return 0;
        }

Another example:


        int main()
        {
            char* pmessage;
            pmessage = "Hello";
            print( pmessage );
            return 0;
        }


Implementing swap( ) function


Suppose that we would like to implement and use a swap function to swap values of two integer variables. A naive idea might look like


                    void swap( int x, int y ) {...}

However, when function parameters are passed by value, the actual arguments of the function will not be affected, because such function receives copies of the original values. More realistic solution is to use pointers:


                    void swap( int* px, int* py ) {...}

A complete example might look like this:


        void swap( int* px, int* py )
        {
            int temp = *px;
            *px = *py;
            *py = temp;
        }

        int main()
        {
            int a = 5;
            int b = 10;
            swap( a, b ); // wrong! address of the variable must be taken
            swap( &a, &b ); // correct
            assert( a == 10 && b == 5 );
            return 0;
        }

Pointer arguments enable a function to access and change objects in the function that called it.


Pointers and Arrays


Pointers and arrays are closely related. For example,


   char amessage[] = "hello"; // array
   char* pmessage = "hello";  // pointer

Construction of the arrays of pointers is also allowed. Most frequent use of arrays of pointers is to store character strings of variable lengths:


   char* months[] = { "Illegal month", "Jan", "Feb", "Mar" };


Command-line Arguments


Your program can gain access to the command line arguments as follows:


    int main( int argc, char* argv[] )
    {
        int i;
        for ( i = 1; i < argc; ++i ) {
            std::cout << argv[i];
        }
        return 0;
    }

Here, argc is the argument counter specifying how many arguments, separated by spaces, were present on the command line. The name of the program itself is also considered to be an argument, so argc will always be equal or greater than one. The second parameter, argv, is the array of pointers to string literals representing the arguments, for example, if a program is invoked by the command

                    C:\> program.exe Hello World
                    

argc will be set to 3, and argv will store values as follows:

    argv:
    1012 ----> "program.exe"
    1023 ----> "Hello"
    1045 ----> "World"
    0
                    

where 1012, 1023, and 1045 are arbitrary addresses of the corresponding string literals in memory.


References


References are alternative names for variables. As such, references can be used in many places instead of pointers. As a result, references simplify notation. For example, the above swap function could be rewritten as:


        void swap( int& x, int& y )
        {
            int temp = x;
            x = y;
            y = temp;
        }

        int main()
        {
            int a = 5;
            int b = 10;
            swap( a, b );
            assert( a == 10 && b == 5 );
            return 0;
        }