banner



How To Assign Values To Registers In C

C++ Programming Language

Pointers, References and Dynamic Memory Allocation

Pointers, References and Dynamic Memory Allocation are the most powerful features in C/C++ language, which allows programmers to directly dispense memory to efficiently manage the retentivity - the most critical and scarce resource in estimator - for best performance. However, "pointer" is also the most complex and difficult feature in C/C++ language.

Pointers are extremely powerful because they allows yous to access addresses and dispense their contents. Just they are also extremely complex to handle. Using them correctly, they could greatly improve the efficiency and performance. On the other hand, using them incorrectly could lead to many problems, from un-readable and un-maintainable codes, to infamous bugs such equally memory leaks and buffer overflow, which may expose your system to hacking. Many new languages (such as Java and C#) remove pointer from their syntax to avoid the pitfalls of pointers, by providing automatic memory direction.

Although you can write C/C++ programs without using pointers, however, it is difficult not to mention pointer in teaching C/C++ language. Arrow is probably not meant for novices and dummies.

Arrow Variables

A computer retentiveness location has an address and holds a content. The accost is a numerical number (oft expressed in hexadecimal), which is difficult for programmers to use straight. Typically, each address location holds 8-scrap (i.due east., 1-byte) of data. It is entirely up to the programmer to interpret the pregnant of the data, such as integer, real number, characters or strings.

To ease the brunt of programming using numerical address and programmer-interpreted data, early programming languages (such every bit C) introduce the concept of variables. A variable is a named location that can store a value of a particular type. Instead of numerical addresses, names (or identifiers) are fastened to certain addresses. Also, types (such as int, double, char) are associated with the contents for ease of interpretation of data.

Each address location typically hold 8-bit (i.e., 1-byte) of data. A 4-byte int value occupies 4 memory locations. A 32-scrap system typically uses 32-flake addresses. To store a 32-scrap address, iv retentiveness locations are required.

The post-obit diagram illustrate the relationship between computers' memory address and content; and variable'south name, type and value used by the programmers.

MemoryAddressContent.png

Pointer Variables (or Pointers)

A arrow variable (or pointer in short) is basically the same equally the other variables, which tin can shop a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a retentiveness accost.

Declaring Pointers

Pointers must be declared before they can exist used, only similar a normal variable. The syntax of declaring a pointer is to place a * in front of the name. A pointer is associated with a type (such every bit int and double) likewise.

          type          *ptr;              blazon*          ptr;           type          *          ptr;        

For case,

int * iPtr;                       double * dPtr;        

Take note that yous need to place a * in forepart of each arrow variable, in other words, * applies only to the name that followed. The * in the announcement statement is not an operator, simply indicates that the proper noun followed is a pointer variable. For example,

int *p1, *p2, i;     int* p1, p2, i;      int * p1, * p2, i;        

Naming Convention of Pointers: Include a "p" or "ptr" as prefix or suffix, east.g., iPtr, numberPtr, pNumber, pStudent.

Initializing Pointers via the Address-Of Operator (&)

When you declare a arrow variable, its content is not initialized. In other words, it contains an address of "somewhere", which is of course non a valid location. This is dangerous! Yous need to initialize a pointer by assigning it a valid address. This is usually done via the address-of operator (&).

The accost-of operator (&) operates on a variable, and returns the accost of the variable. For case, if number is an int variable, &number returns the address of the variable number.

Y'all can use the address-of operator to get the address of a variable, and assign the accost to a arrow variable. For instance,

int number = 88;      int * pNumber;                 pNumber = &number;             int * pAnother = &number;        

PointerDeclaration.png

As illustrated, the int variable number, starting at address 0x22ccec, contains an int value 88. The expression &number returns the address of the variable number, which is 0x22ccec. This address is then assigned to the pointer variable pNumber, as its initial value.

The address-of operator (&) can only be used on the RHS.

Indirection or Dereferencing Operator (*)

The indirection operator (or dereferencing operator) (*) operates on a arrow, and returns the value stored in the address kept in the pointer variable. For case, if pNumber is an int arrow, *pNumber returns the int value "pointed to" by pNumber.

For example,

int number = 88; int * pNumber = &number;   cout << pNumber<< endl;    cout <<          *pNumber          << endl;  *pNumber          = 99;             cout <<          *pNumber          << endl;  cout << number << endl;        

Accept note that pNumber stores a memory address location, whereas *pNumber refers to the value stored in the accost kept in the pointer variable, or the value pointed to by the pointer.

As illustrated, a variable (such equally number) directly references a value, whereas a arrow indirectly references a value through the retention accost it stores. Referencing a value indirectly via a arrow is chosen indirection or dereferencing.

The indirection operator (*) tin exist used in both the RHS (temp = *pNumber) and the LHS (*pNumber = 99) of an assignment argument.

Take note that the symbol * has different meaning in a declaration argument and in an expression. When it is used in a declaration (due east.g., int * pNumber), information technology denotes that the name followed is a pointer variable. Whereas when it is used in a expression (e.g., *pNumber = 99 ; temp << *pNumber;), it refers to the value pointed to by the pointer variable.

Pointer has a Type Too

A pointer is associated with a type (of the value it points to), which is specified during declaration. A pointer can only hold an address of the declared type; it cannot hold an accost of a different type.

int i = 88; double d = 55.66; int * iPtr = &i;     double * dPtr = &d;    iPtr = &d;          // Fault, cannot concord address of different blazon          dPtr = &i;          // Error          iPtr = i;          // Fault, pointer holds address of an int, Non int value          int j = 99; iPtr = &j;        
Case
1 2 3 4 5 6 7 8 nine ten xi 12 13 14 xv 16 17 xviii 19 20 21 22 23
                    #include <iostream> using namespace std;   int main() {    int number = 88;        int * pNumber;          pNumber = &number;        cout << pNumber << endl;      cout << &number << endl;      cout << *pNumber << endl;     cout << number << endl;         *pNumber = 99;                cout << pNumber << endl;      cout << &number << endl;      cout << *pNumber << endl;     cout << number << endl;                                       cout << &pNumber << endl;  }

Notes: The address values that you get are unlikely to be the same every bit mine. The Os loads the program in available free retention locations, instead of fixed memory locations.

Uninitialized Pointers

The following lawmaking fragment has a serious logical error!

int * iPtr; *iPtr = 55; cout << *iPtr << endl;

The pointer iPtr was declared without initialization, i.e., it is pointing to "somewhere" which is of course an invalid retention location. The *iPtr = 55 corrupts the value of "somewhere"! Yous need to initialize a pointer by assigning information technology a valid accost. Near of the compilers does not indicate an error or a warning for uninitialized pointer?!

Null Pointers

You can initialize a pointer to 0 or NULL, i.e., information technology points to cipher. It is chosen a zero pointer. Dereferencing a zippo pointer (*p) causes an STATUS_ACCESS_VIOLATION exception.

int * iPtr = 0;          cout <<          *iPtr          << endl;          // Mistake! STATUS_ACCESS_VIOLATION exception          int * p = NULL;        

Initialize a pointer to zero during annunciation is a good software applied science practise.

C++11 introduces a new keyword called nullptr to represent nix pointer.

Reference Variables

C++ added the so-called reference variables (or references in short). A reference is an alias, or an alternate proper noun to an existing variable. For instance, suppose yous make peter a reference (alias) to paul, you can refer to the person as either peter or paul.

The main apply of references is interim equally function formal parameters to support laissez passer-by-reference. In an reference variable is passed into a function, the role works on the original copy (instead of a clone copy in pass-by-value). Changes inside the function are reflected outside the function.

A reference is similar to a pointer. In many cases, a reference tin be used every bit an alternative to pointer, in particular, for the function parameter.

References (or Aliases) (&)

Recollect that C/C++ use & to announce the address-of operator in an expression. C++ assigns an boosted meaning to & in declaration to declare a reference variable.

The meaning of symbol & is different in an expression and in a declaration. When it is used in an expression, & denotes the address-of operator, which returns the address of a variable, due east.g., if number is an int variable, &number returns the address of the variable number (this has been described in the above section).

Howeve, when & is used in a declaration (including part formal parameters), it is office of the type identifier and is used to declare a reference variable (or reference or allonym or alternate name). Information technology is used to provide another name, or some other reference, or alias to an existing variable.

The syntax is as follow:

          blazon          &newName          =          existingName;           type&          newName          =          existingName;           type          &          newName          =          existingName;        

It shall exist read every bit " newName is a reference to exisitngName ", or " newNew is an alias of existingName ". You tin now refer to the variable as newName or existingName .

For example,

i ii 3 4 five half-dozen 7 8 nine ten xi 12 13 xiv fifteen 16 17 eighteen nineteen 20
                    #include <iostream> using namespace std;   int main() {    int number = 88;                            int & refNumber = number;                                                      cout << number << endl;        cout <<                  refNumber                  << endl;                   refNumber = 99;                cout <<                  refNumber                  << endl;    cout << number << endl;          number = 55;                   cout << number << endl;    cout <<                  refNumber                  << endl;  }

PointerReferencing.png

How References Work?

A reference works as a arrow. A reference is declared as an alias of a variable. It stores the address of the variable, every bit illustrated:

ReferenceIsAPointer.png

References vs. Pointers

Pointers and references are equivalent, except:

  1. A reference is a name constant for an accost. You need to initialize the reference during declaration.
                  int & iRef;            
    Once a reference is established to a variable, y'all cannot modify the reference to reference some other variable.
  2. To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g., if pNumber is a int pointer, *pNumber returns the value pointed to past pNumber. It is called dereferencing or indirection). To assign an accost of a variable into a pointer, you need to use the address-of operator & (east.g., pNumber = &number).
    On the other hand, referencing and dereferencing are done on the references implicitly. For example, if refNumber is a reference (alias) to another int variable, refNumber returns the value of the variable. No explicit dereferencing operator * should be used. Furthermore, to assign an address of a variable to a reference variable, no accost-of operator & is needed.

For example,

1 2 3 iv 5 6 vii 8 9 10 xi 12 13 fourteen fifteen 16 17 xviii 19 20 21 22 23 24 25 26 27 28 29 thirty 31
                    #include <iostream> using namespace std;   int master() {    int number1 = 88, number2 = 22;         int * pNumber1 = &number1;     *pNumber1 = 99;                cout << *pNumber1 << endl;     cout << &number1 << endl;      cout << pNumber1 << endl;      cout << &pNumber1 << endl;     pNumber1 = &number2;                int & refNumber1 = number1;     refNumber1 = 11;                cout << refNumber1 << endl;     cout << &number1 << endl;       cout << &refNumber1 << endl;                                       refNumber1 = number2;                                             number2++;       cout << refNumber1 << endl;      cout << number1 << endl;         cout << number2 << endl;      }

A reference variable provides a new name to an existing variable. It is dereferenced implicitly and does not need the dereferencing operator * to call back the value referenced. On the other hand, a pointer variable stores an address. You can modify the accost value stored in a pointer. To retrieve the value pointed to by a arrow, you lot need to use the indirection operator *, which is known every bit explicit dereferencing. Reference can exist treated as a const pointer. It has to be initialized during announcement, and its content cannot be changed.

Reference is closely related to pointer. In many cases, it can be used every bit an culling to arrow. A reference allows yous to manipulate an object using arrow, only without the pointer syntax of referencing and dereferencing.

The to a higher place example illustrates how reference works, only does not evidence its typical usage, which is used as the role formal parameter for laissez passer-by-reference.

Pass-By-Reference into Functions with Reference Arguments vs. Pointer Arguments

Laissez passer-by-Value

In C/C++, by default, arguments are passed into functions past value (except arrays which is treated every bit pointers). That is, a clone copy of the argument is made and passed into the office. Changes to the clone copy inside the function has no outcome to the original argument in the caller. In other words, the called role has no access to the variables in the caller. For example,

1 2 3 4 5 6 7 eight 9 10 11 12 thirteen 14 15 16 17 18 19
                    #include <iostream> using namespace std;   int foursquare(int);   int main() {    int number = 8;    cout <<  "In master(): " << &number << endl;     cout << number << endl;            cout << square(number) << endl;    cout << number << endl;         }   int square(int due north) {      cout <<  "In square(): " << &n << endl;     n *= n;           return due north; }

The output conspicuously shows that at that place are two different addresses.

Pass-by-Reference with Pointer Arguments

In many situations, we may wish to change the original copy directly (especially in passing huge object or array) to avoid the overhead of cloning. This can be done by passing a pointer of the object into the function, known every bit pass-by-reference. For example,

ane 2 iii 4 5 vi vii 8 ix ten 11 12 13 14 15 xvi 17 18
                    #include <iostream> using namespace std;   void foursquare(int *);   int chief() {    int number = 8;    cout <<  "In main(): " << &number << endl;     cout << number << endl;      square(&number);             cout << number << endl;   }   void square(int * pNumber) {     cout <<  "In foursquare(): " << pNumber << endl;                   *pNumber                  *=                  *pNumber;      }

The called function operates on the same address, and can thus modify the variable in the caller.

Pass-by-Reference with Reference Arguments

Instead of passing pointers into role, you could besides laissez passer references into office, to avoid the clumsy syntax of referencing and dereferencing. For example,

ane ii 3 4 5 6 7 eight 9 10 11 12 13 14 xv 16 17 18
                    #include <iostream> using namespace std;   void square(int &);   int main() {    int number = 8;    cout <<  "In main(): " << &number << endl;     cout << number << endl;     square(number);             cout << number << endl;  }   void square(int & rNumber) {     cout <<  "In square(): " << &rNumber << endl;                   rNumber                  *=                  rNumber;        }

Again, the output shows that the called function operates on the same address, and can thus modify the caller's variable.

Have annotation referencing (in the caller) and dereferencing (in the function) are done implicitly. The but coding difference with pass-by-value is in the function's parameter declaration.

Recall that references are to be initialized during declaration. In the case of part formal parameter, the references are initialized when the function is invoked, to the caller's arguments.

References are primarily used in passing reference in/out of functions to allow the called office accesses variables in the caller directly.

"const" Part Reference/Pointer Parameters

A const role formal parameter cannot be modified inside the role. Use const whenever possible every bit it protects you from inadvertently modifying the parameter and protects you confronting many programming errors.

A const function parameter can receive both const and non-const argument. On the other hand, a non-const function reference/pointer parameter can but receive non-const argument. For instance,

i 2 3 iv 5 6 7 8 ix 10 11 12 xiii 14 15 16 17 eighteen 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 twoscore 41 42
                    #include <iostream> using namespace std;   int squareConst(const int); int squareNonConst(int); int squareConstRef(const int &); int squareNonConstRef(int &);   int main() {    int number = 8;    const int constNumber = 9;    cout << squareConst(number) << endl;    cout << squareConst(constNumber) << endl;    cout << squareNonConst(number) << endl;    cout << squareNonConst(constNumber) << endl;      cout << squareConstRef(number) << endl;    cout << squareConstRef(constNumber) << endl;    cout << squareNonConstRef(number) << endl;                  cout << squareNonConstRef(constNumber) << endl;                          }   int squareConst(const int number) {                      number *= number;                      return number * number; }   int squareNonConst(int number) {     number *= number;    return number; }   int squareConstRef(const int & number) {     render number * number; }   int squareNonConstRef(int & number) {     return number * number; }

Passing the Function's Return Value

Passing the Return-value as Reference

Yous tin can besides pass the return-value as reference or arrow. For example,

1 2 iii 4 five six 7 viii ix 10 11 12 13 14 fifteen 16 17 eighteen 19 20 21 22 23 24 25 26 27 28 29 thirty 31 32 33 34
                    #include <iostream> using namespace std;   int & squareRef(int &); int * squarePtr(int *);   int principal() {    int number1 = 8;    cout <<  "In main() &number1: " << &number1 << endl;     int & result = squareRef(number1);    cout <<  "In main() &result: " << &result << endl;     cout << effect << endl;      cout << number1 << endl;       int number2 = 9;    cout <<  "In chief() &number2: " << &number2 << endl;     int * pResult = squarePtr(&number2);    cout <<  "In main() pResult: " << pResult << endl;     cout << *pResult << endl;      cout << number2 << endl;    }   int & squareRef(int & rNumber) {    cout <<  "In squareRef(): " << &rNumber << endl;     rNumber *= rNumber;    return rNumber; }   int * squarePtr(int * pNumber) {    cout <<  "In squarePtr(): " << pNumber << endl;     *pNumber *= *pNumber;    render pNumber; }
You should not pass Function'south local variable as return value by reference
ane 2 3 4 5 6 7 viii 9 ten 11 12 13 fourteen xv 16 17 xviii nineteen 20 21 22 23 24 25
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int chief() {    int number = 8;    cout << number << endl;     cout << *squarePtr(number) << endl;     cout << squareRef(number) << endl;   }   int * squarePtr(int number) {    int localResult = number * number;    return &localResult;       }   int & squareRef(int number) {    int localResult = number * number;    return localResult;       }

This programme has a serious logical mistake, equally local variable of function is passed back as return value by reference. Local variable has local scope within the function, and its value is destroyed after the part exits. The GCC compiler is kind enough to outcome a warning (only non error).

It is safe to return a reference that is passed into the function every bit an statement. Run into earlier examples.

Passing Dynamically Allocated Memory as Return Value past Reference

Instead, you need to dynamically allocate a variable for the return value, and return it by reference.

ane 2 3 4 five 6 7 8 9 10 eleven 12 13 xiv 15 sixteen 17 18 19 xx 21 22 23
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int chief() {    int number = 8;    cout << number << endl;     cout << *squarePtr(number) << endl;     cout << squareRef(number) << endl;   }   int * squarePtr(int number) {    int * dynamicAllocatedResult = new int(number * number);    return dynamicAllocatedResult; }   int & squareRef(int number) {    int * dynamicAllocatedResult = new int(number * number);    return *dynamicAllocatedResult; }

Summary

Pointers and references are highly complex and difficult to master. But they can greatly ameliorate the efficiency of the programs.

For novices, avoid using pointers in your programme. Improper usage can lead to serious logical bugs. However, you lot need to understand the syntaxes of pass-past-reference with pointers and references, because they are used in many library functions.

  • In pass-by-value, a clone is made and passed into the function. The caller'due south copy cannot be modified.
  • In laissez passer-by-reference, a pointer is passed into the function. The caller's copy could be modified inside the function.
  • In pass-by-reference with reference arguments, you utilize the variable name as the argument.
  • In laissez passer-by-reference with pointer arguments, you lot need to employ &varName (an address) every bit the argument.

Dynamic Memory Allotment

new and delete Operators

Instead of ascertain an int variable (int number), and assign the address of the variable to the int arrow (int *pNumber = &number), the storage can be dynamically allocated at runtime, via a new operator. In C++, whenever you lot classify a piece of memory dynamically via new, y'all need to use delete to remove the storage (i.e., to return the storage to the heap).

The new operation returns a pointer to the memory allocated. The delete operator takes a pointer (pointing to the memory allocated via new) as its sole statement.

For example,

            int number = 88; int * p1 = &number;               int * p2;           cout << p2 << endl;           p2 = new int;                             *p2 = 99; cout << p2 << endl;   cout << *p2 << endl;           delete p2;        

Observe that new and delete operators piece of work on pointer.

To initialize the allocated memory, you tin can use an initializer for fundamental types, or invoke a constructor for an object. For example,

            int * p1 = new int(88); double * p2 = new double(one.23);    int * p1 = new int {88}; double * p2 = new double {1.23};    Date * date1 = new Date(1999, one, 1);   Time * time1 = new Time(12, 34, 56);

You lot can dynamically classify storage for global pointers inside a function. Dynamically allocated storage inside the function remains fifty-fifty after the function exits. For example,

1 ii iii four 5 half-dozen 7 eight 9 10 11 12 13 14 fifteen 16 17 18 19 20 21 22
                    #include <iostream> using namespace std;   int * p1, * p2;       void allocate() {    p1 = new int;         *p1 = 88;             p2 = new int(99);  }   int main() {    allocate();    cout << *p1 << endl;      cout << *p2 << endl;      delete p1;      delete p2;    return 0; }

The main differences between static allocation and dynamic allocations are:

  1. In static allocation, the compiler allocates and deallocates the storage automatically, and handle memory direction. Whereas in dynamic allocation, y'all, as the programmer, handle the memory allocation and deallocation yourself (via new and delete operators). You have full control on the pointer addresses and their contents, as well as retention management.
  2. Static allocated entities are manipulated through named variables. Dynamic allocated entities are handled through pointers.

new[] and delete[] Operators

Dynamic array is allocated at runtime rather than compile-time, via the new[] operator. To remove the storage, yous need to utilize the delete[] operator (instead of simply delete). For example,

ane 2 iii iv 5 vi 7 8 9 ten xi 12 13 fourteen fifteen 16 17 18 nineteen 20 21 22 23 24
                    #include <iostream> #include <cstdlib> using namespace std;   int main() {    const int SIZE = five;    int * pArray;      pArray = new int[SIZE];            for (int i = 0; i < SIZE; ++i) {       *(pArray + i) = rand() % 100;    }        for (int i = 0; i < SIZE; ++i) {       cout << *(pArray + i) << " ";    }    cout << endl;      delete[] pArray;      return 0; }

C++03 does not let your to initialize the dynamically-allocated array. C++11 does with the brace initialization, as follows:

            int * p = new int[five] {i, 2, 3, iv, 5};

Pointer, Array and Function

Array is Treated every bit Pointer

In C/C++, an assortment's name is a arrow, pointing to the first element (alphabetize 0) of the array. For case, suppose that numbers is an int assortment, numbers is a also an int pointer, pointing at the first element of the assortment. That is, numbers is the aforementioned equally &numbers[0]. Consequently, *numbers is number[0]; *(numbers+i) is numbers[i].

For case,

1 2 3 iv 5 6 vii viii nine 10 eleven 12 xiii 14 15 16
                    #include <iostream> using namespace std;   int main() {    const int SIZE = 5;    int numbers[SIZE] = {11, 22, 44, 21, 41};                cout << &numbers[0] << endl;     cout << numbers << endl;         cout << *numbers << endl;             cout << *(numbers + i) << endl;       cout << *(numbers + 4) << endl;    }

Pointer Arithmetic

As seen from the previous department, if numbers is an int array, it is treated every bit an int pointer pointing to the showtime element of the assortment. (numbers + ane) points to the next int, instead of having the next sequential address. Accept annotation that an int typically has 4 bytes. That is (numbers + 1) increases the address by four, or sizeof(int). For example,

int numbers[] = {11, 22, 33}; int * iPtr = numbers; cout << iPtr << endl;         cout << iPtr + ane << endl;     cout << *iPtr << endl;        cout << *(iPtr + ane) << endl;   cout << *iPtr + 1 << endl;        

sizeof Array

The functioning sizeof(arrayName) returns the full bytes of the array. You can derive the length (size) of the array by dividing it with the size of an element (e.g. element 0). For example,

                    int numbers[100];          cout <<          sizeof(numbers)          << endl;      cout <<          sizeof(numbers[0])          << endl;   cout << "Array size is " << sizeof(numbers) / sizeof(numbers[0]) << endl;        

Passing Assortment In/Out of a Function

An array is passed into a part as a pointer to the first element of the array. You can use assortment note (due east.g., int[]) or pointer notation (e.grand., int*) in the function declaration. The compiler always treats it as pointer (east.yard., int*). For example, the following declarations are equivalent:

int max(int numbers[], int size); int max(int *numbers, int size); int max(int number[50], int size);

They will be treated as int* by the compiler, every bit follow. The size of the array given in [] is ignored.

int max(int*, int);

Array is passed past reference into the function, because a arrow is passed instead of a clone copy. If the array is modified inside the function, the modifications are applied to the caller's copy. You could declare the assortment parameter equally const to prevent the array from being modified inside the function.

The size of the array is non function of the array parameter, and needs to be passed in some other int parameter. Compiler is not able to deduce the array size from the assortment pointer, and does not perform array bound check.

Example: Using the usual array annotation.

i 2 3 4 5 6 vii 8 9 x 11 12 thirteen 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
                    #include <iostream> using namespace std;    int max(const int arr[], int size); void replaceByMax(int arr[], int size); void impress(const int arr[], int size);   int main() {    const int SIZE = 4;    int numbers[SIZE] = {eleven, 22, 33, 22};    impress(numbers, SIZE);    cout << max(numbers, SIZE) << endl;    replaceByMax(numbers, SIZE);    print(numbers, SIZE); }     int max(const int arr[], int size) {    int max = arr[0];    for (int i = 1; i < size; ++i) {       if (max < arr[i]) max = arr[i];    }    return max; }     void replaceByMax(int arr[], int size) {    int maxValue = max(arr, size);    for (int i = 0; i < size; ++i) {       arr[i] = maxValue;    } }    void impress(const int arr[], int size) {    cout << "{";    for (int i = 0; i < size; ++i) {       cout << arr[i];       if (i < size - 1) cout << ",";    }    cout << "}" << endl; }

Take note that you can change the contents of the caller's assortment inside the function, as array is passed by reference. To prevent accidental modification, you could utilize const qualifier to the function'southward parameter. Retrieve that const inform the compiler that the value should not be changed. For example, suppose that the role print() prints the contents of the given assortment and does not change the array, you could apply const to both the array proper noun and its size, as they are not expected to be inverse within the part.

void print(const          int arr[],          int          size);

Compiler flags out an error "assignment of read-but location" if it detected a const value would be changed.

Case: Using pointer notation.

1 ii 3 iv 5 six 7 8 9 x 11 12 13 xiv 15 16 17 eighteen 19 xx 21
                    #include <iostream> using namespace std;    int max(const int *arr, int size);   int main() {    const int SIZE = 5;    int numbers[SIZE] = {10, xx, 90, 76, 22};    cout << max(numbers, SIZE) << endl; }    int max(const int *arr, int size) {    int max =                  *arr;    for (int i = 1; i < size; ++i) {       if (max <                  *(arr+i)) max =                  *(arr+i);    }    return max; }

Pass-by-Reference and sizeof

ane 2 three four 5 6 seven 8 ix 10 11 12 13 fourteen 15 sixteen 17 18 19 20 21
                    #include <iostream> using namespace std;    void fun(const int *arr, int size);    int primary() {    const int SIZE = v;    int a[SIZE] = {8, four, five, 3, ii};    cout << "sizeof in main() is " <<                  sizeof(a)                  << endl;    cout << "address in main() is " << a << endl;    fun(a, SIZE); }    void fun(const int *arr, int size) {    cout << "sizeof in function is " <<                  sizeof(arr)                  << endl;    cout << "address in function is " << arr << endl; }
sizeof in main() is 20 address in main() is 0x22fefc sizeof in role is iv accost in part is 0x22fefc

The accost of arrays in primary() and the office are the same, every bit expected, as array is passed by reference.

In main(), the sizeof assortment is twenty (4 bytes per int, length of 5). Within the function, the sizeof is 4, which is the sizeof int arrow (four-byte address). This is why you need to pass the size into the function.

Operating on a Range of an Assortment

1 ii iii 4 five half-dozen 7 8 9 x 11 12 13 14 15 sixteen 17 18 xix xx 21 22 23 24 25
                    #include <iostream> using namespace std;    int sum(const int *begin, const int *end);    int principal() {    int a[] = {8, iv, five, 3, 2, 1, 4, 8};    cout << sum(a, a+eight) << endl;           cout << sum(a+2, a+5) << endl;         cout << sum(&a[2], &a[v]) << endl;  }      int sum(const int *begin, const int *terminate) {    int sum = 0;    for (const int *p = brainstorm; p != finish; ++p) {       sum += *p;    }    render sum; }

Program Notes:

  • To write a role that operates on a range of the given array, yous can laissez passer the begin pointer and the terminate arrow into the function. By convention, the functioning shall showtime at the brainstorm arrow, upward to the finish pointer, but excluding the terminate arrow.
  • In "const int *p", *p (content pointed-to) is abiding, but p is not constant.

C-String and Pointer

C-string (of the C language) is a character array, terminated with a null character '\0'. For example,

1 two 3 4 5 six 7 eight 9 x 11 12 13 14 15 sixteen 17 eighteen 19 xx 21 22 23 24 25 26 27
                    #include <iostream> #include <cstring> using namespace std;   int master() {    char msg1[] = "Howdy";    char *msg2 = "Hello";            cout << strlen(msg1) << endl;       cout << strlen(msg2) << endl;    cout << strlen("Hello") << endl;      int size = sizeof(msg1)/sizeof(char);    cout << size << endl;     for (int i = 0; msg1[i] != '\0'; ++i) {       cout << msg1[i];    }    cout << endl;      for (char *p = msg1; *p != '\0'; ++p) {                 cout << *p;    }    cout << endl; }

Take note that for C-String office such every bit strlen() (in header cstring, ported over from C'south string.h), there is no need to laissez passer the array length into the function. This is considering C-Strings are terminated by '\0'. The function tin iterate thru the characters in the array until '\0'. For case,

one 2 3 iv v 6 vii viii 9 10 eleven 12 13 fourteen 15 16 17 18 19 twenty 21 22 23 24 25 26
                    #include <iostream> #include <cstring> using namespace std;   int count(const char *str, const char c);     int principal() {    char msg1[] = "Hello, earth";    char *msg2 = "Hi, world";      cout << count(msg1, 'l') << endl;    cout << count(msg2, 'l') << endl;    cout << count("Hello, world", 'fifty') << endl; }     int count(const char *str, const char c) {    int count = 0;    while (*str) {          if (*str == c) ++count;       ++str;    }    render count; }

*More On Pointers

Function Pointer

In C/C++, functions, similar all data items, take an accost. The name of a office is the starting address where the function resides in the retention, and therefore, can be treated as a pointer. We tin pass a function pointer into role as well. The syntax for declaring a function arrow is:

            return-blazon          (*          office-ptr-name) (parameter-listing)    double (*fp)(int, int)   double *dp;              double *fun(int, int)     double f(int, int);       fp = f;        
Example
ane ii iii 4 5 6 7 8 9 x 11 12 13 fourteen fifteen 16 17 18 19 20 21 22 23 24 25
                    #include <iostream> using namespace std;   int arithmetic(int, int,                  int (*)(int, int));       int add(int, int); int sub(int, int);   int add(int n1, int n2) { render n1 + n2; } int sub(int n1, int n2) { render n1 - n2; }   int arithmetics(int n1, int n2,                  int (*operation) (int, int)) {    return                  (*operation)(n1, n2); }   int main() {    int number1 = 5, number2 = 6;          cout << arithmetic(number1, number2, add) << endl;        cout << arithmetic(number1, number2, sub) << endl; }

Generic Pointer or void Pointer (void *)

A void pointer can hold address of any data type (except function arrow). We cannot operate on the object pointed to past void arrow, every bit the blazon is unknown. We can apply a void pointer to compare with another address.

[TODO] Example

Constant Pointer vs. Constant Pointed-to Data

  1. Not-constant pointer to constant data: Data pointed to CANNOT exist changed; just pointer Can exist changed to point to another data. For example,
    int i1 = viii, i2 = 9;              const              int * iptr = &i1;   // *iptr = 9;              // error: consignment of read-only location              iptr = &i2;            
  2. Constant pointer to non-constant information: Data pointed to CAN exist inverse; but pointer CANNOT be changed to point to some other data. For example,
    int i1 = 8, i2 = 9; int *              const              iptr = &i1;   *iptr = 9;    // iptr = &i2;              // mistake: assignment of read-only variable            
  3. Constant pointer to constant data: Data pointed to CANNOT exist inverse; and pointer CANNOT be changed to bespeak to another data. For example,
    int i1 = viii, i2 = 9;              const              int *              const              iptr = &i1;   // *iptr = 9;              // fault: assignment of read-only variable              // iptr = &i2;              // fault: assignment of read-only variable            
  4. Non-constant pointer to non-constant data: Information pointed to Tin be changed; and pointer Tin be changed to indicate to some other data. For example,
    int i1 = 8, i2 = 9; int *              iptr = &i1;   *iptr = ix;    iptr = &i2;            

Link to "C++ References & Resources"

Source: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp4_PointerReference.html

Posted by: gamblindrined.blogspot.com

0 Response to "How To Assign Values To Registers In C"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel