Skip to content Skip to sidebar Skip to footer

How to Read in a Char for a Double Function C++

C++ Programming Linguistic communication

Pointers, References and Dynamic Memory Resource allotment

Pointers, References and Dynamic Memory Allocation are the well-nigh powerful features in C/C++ language, which allows programmers to straight manipulate memory to efficiently manage the memory - the most critical and scarce resource in computer - for all-time performance. All the same, "pointer" is too the almost complex and difficult characteristic in C/C++ language.

Pointers are extremely powerful because they allows you to access addresses and dispense their contents. But they are besides extremely complex to handle. Using them correctly, they could greatly improve the efficiency and functioning. On the other hand, using them incorrectly could lead to many bug, from un-readable and un-maintainable codes, to infamous bugs such as 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 retentivity direction.

Although y'all can write C/C++ programs without using pointers, withal, it is difficult non to mention pointer in teaching C/C++ linguistic communication. Arrow is probably not meant for novices and dummies.

Pointer Variables

A computer memory location has an address and holds a content. The accost is a numerical number (frequently expressed in hexadecimal), which is hard for programmers to utilise directly. Typically, each accost location holds eight-bit (i.e., 1-byte) of data. It is entirely up to the programmer to interpret the significant 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) innovate the concept of variables. A variable is a named location that can store a value of a item 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 information.

Each address location typically agree eight-bit (i.due east., 1-byte) of data. A four-byte int value occupies 4 retentiveness locations. A 32-bit system typically uses 32-chip addresses. To store a 32-scrap address, iv memory locations are required.

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

MemoryAddressContent.png

Pointer Variables (or Pointers)

A arrow variable (or pointer in brusque) is basically the aforementioned as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such equally an int, a double, a char), a pointer stores a memory accost.

Declaring Pointers

Pointers must be alleged before they tin be used, just similar a normal variable. The syntax of declaring a pointer is to place a * in front of the proper noun. A pointer is associated with a type (such as int and double) also.

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

For example,

int * iPtr;                       double * dPtr;        

Take note that you demand to place a * in forepart of each pointer variable, in other words, * applies only to the proper noun that followed. The * in the annunciation statement is non an operator, but indicates that the proper noun followed is a pointer variable. For case,

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

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

Initializing Pointers via the Accost-Of Operator (&)

When you declare a pointer 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 normally done via the address-of operator (&).

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

Yous can use the accost-of operator to go the address of a variable, and assign the address to a arrow variable. For example,

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 accost-of operator (&) tin can simply exist used on the RHS.

Indirection or Dereferencing Operator (*)

The indirection operator (or dereferencing operator) (*) operates on a pointer, and returns the value stored in the address kept in the pointer variable. For example, if pNumber is an int pointer, *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 past the pointer.

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

The indirection operator (*) can exist used in both the RHS (temp = *pNumber) and the LHS (*pNumber = 99) of an consignment statement.

Take notation that the symbol * has different significant in a proclamation statement and in an expression. When it is used in a proclamation (e.g., int * pNumber), information technology denotes that the name followed is a pointer variable. Whereas when information technology is used in a expression (e.g., *pNumber = 99 ; temp << *pNumber;), it refers to the value pointed to past the arrow variable.

Pointer has a Type Too

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

int i = 88; double d = 55.66; int * iPtr = &i;     double * dPtr = &d;    iPtr = &d;          // ERROR, cannot concur accost of unlike type          dPtr = &i;          // Mistake          iPtr = i;          // Error, pointer holds address of an int, NOT int value          int j = 99; iPtr = &j;        
Instance
1 2 3 four five six 7 viii nine 10 eleven 12 13 xiv xv sixteen 17 18 19 20 21 22 23
                    #include <iostream> using namespace std;   int master() {    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 as mine. The Bone 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 arrow iPtr was declared without initialization, i.east., it is pointing to "somewhere" which is of form an invalid memory location. The *iPtr = 55 corrupts the value of "somewhere"! Y'all need to initialize a pointer by assigning information technology a valid address. Most of the compilers does not signal an mistake or a warning for uninitialized pointer?!

Null Pointers

You can initialize a arrow to 0 or NULL, i.e., information technology points to nothing. It is called a zip arrow. Dereferencing a null pointer (*p) causes an STATUS_ACCESS_VIOLATION exception.

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

Initialize a pointer to zip during declaration is a proficient software engineering practice.

C++eleven introduces a new keyword called nullptr to stand for null arrow.

Reference Variables

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

The principal employ of references is acting as part formal parameters to back up pass-by-reference. In an reference variable is passed into a function, the office works on the original copy (instead of a clone re-create in pass-by-value). Changes inside the function are reflected exterior the function.

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

References (or Aliases) (&)

Call up that C/C++ use & to denote the address-of operator in an expression. C++ assigns an additional pregnant to & in annunciation to declare a reference variable.

The pregnant of symbol & is dissimilar in an expression and in a announcement. When it is used in an expression, & denotes the accost-of operator, which returns the address of a variable, e.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 function formal parameters), information technology is part of the type identifier and is used to declare a reference variable (or reference or alias or alternating name). It is used to provide another name, or another reference, or alias to an existing variable.

The syntax is as follow:

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

It shall be read as " newName is a reference to exisitngName ", or " newNew is an allonym of existingName ". You can now refer to the variable as newName or existingName .

For example,

i 2 three 4 5 vi vii 8 9 10 eleven 12 13 14 fifteen xvi 17 18 19 xx
                    #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. Information technology stores the address of the variable, as illustrated:

ReferenceIsAPointer.png

References vs. Pointers

Pointers and references are equivalent, except:

  1. A reference is a proper noun constant for an accost. You need to initialize the reference during declaration.
                  int & iRef;            
    Once a reference is established to a variable, you cannot change the reference to reference another variable.
  2. To get the value pointed to past 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 address of a variable into a pointer, you demand to use the address-of operator & (eastward.g., pNumber = &number).
    On the other hand, referencing and dereferencing are done on the references implicitly. For case, if refNumber is a reference (allonym) 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 address-of operator & is needed.

For example,

1 2 3 4 5 6 seven 8 9 ten xi 12 13 14 15 xvi 17 eighteen 19 xx 21 22 23 24 25 26 27 28 29 xxx 31
                    #include <iostream> using namespace std;   int main() {    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 retrieve the value referenced. On the other hand, a pointer variable stores an address. Yous can change the address value stored in a arrow. To retrieve the value pointed to by a pointer, you demand to utilize the indirection operator *, which is known equally explicit dereferencing. Reference can be treated every bit a const pointer. It has to exist initialized during proclamation, and its content cannot be changed.

Reference is closely related to pointer. In many cases, it tin can exist used as an alternative to pointer. A reference allows you to manipulate an object using pointer, but without the pointer syntax of referencing and dereferencing.

The in a higher place instance illustrates how reference works, just does not show its typical usage, which is used as the office formal parameter for pass-by-reference.

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

Pass-by-Value

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

one ii 3 iv 5 six vii 8 ix 10 eleven 12 13 14 15 16 17 eighteen 19
                    #include <iostream> using namespace std;   int square(int);   int principal() {    int number = 8;    cout <<  "In chief(): " << &number << endl;     cout << number << endl;            cout << square(number) << endl;    cout << number << endl;         }   int square(int n) {      cout <<  "In square(): " << &n << endl;     north *= n;           render n; }

The output clearly shows that there are two different addresses.

Laissez passer-by-Reference with Pointer Arguments

In many situations, we may wish to change the original copy directly (specially in passing huge object or array) to avert the overhead of cloning. This can exist done past passing a pointer of the object into the role, known as pass-by-reference. For example,

i 2 iii iv 5 6 vii viii 9 10 xi 12 13 14 xv 16 17 18
                    #include <iostream> using namespace std;   void foursquare(int *);   int main() {    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 role 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 function, you could as well laissez passer references into function, to avert the clumsy syntax of referencing and dereferencing. For example,

1 2 3 4 5 vi 7 8 nine 10 11 12 xiii fourteen fifteen 16 17 eighteen
                    #include <iostream> using namespace std;   void square(int &);   int primary() {    int number = viii;    cout <<  "In principal(): " << &number << endl;     cout << number << endl;     foursquare(number);             cout << number << endl;  }   void square(int & rNumber) {     cout <<  "In square(): " << &rNumber << endl;                   rNumber                  *=                  rNumber;        }

Once again, the output shows that the called function operates on the same address, and tin can thus alter the caller's variable.

Accept notation referencing (in the caller) and dereferencing (in the function) are done implicitly. The just coding deviation with pass-by-value is in the part's parameter announcement.

Recall that references are to be initialized during declaration. In the instance of role formal parameter, the references are initialized when the part is invoked, to the caller'due south arguments.

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

"const" Function Reference/Pointer Parameters

A const office formal parameter cannot exist modified inside the function. Utilize const whenever possible equally information technology protects you from inadvertently modifying the parameter and protects you lot against 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 tin only receive non-const statement. For instance,

1 2 3 4 5 6 seven 8 nine 10 11 12 13 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 twoscore 41 42
                    #include <iostream> using namespace std;   int squareConst(const int); int squareNonConst(int); int squareConstRef(const int &); int squareNonConstRef(int &);   int master() {    int number = viii;    const int constNumber = ix;    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) {     return number * number; }   int squareNonConstRef(int & number) {     render number * number; }

Passing the Role's Return Value

Passing the Render-value as Reference

You tin can also pass the return-value as reference or arrow. For example,

1 2 three 4 5 6 vii 8 9 10 11 12 13 xiv fifteen xvi 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
                    #include <iostream> using namespace std;   int & squareRef(int &); int * squarePtr(int *);   int master() {    int number1 = 8;    cout <<  "In main() &number1: " << &number1 << endl;     int & result = squareRef(number1);    cout <<  "In master() &result: " << &result << endl;     cout << result << endl;      cout << number1 << endl;       int number2 = 9;    cout <<  "In principal() &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;    return pNumber; }
Y'all should non pass Function's local variable as return value by reference
i 2 three 4 v six seven 8 9 10 11 12 13 xiv 15 sixteen 17 eighteen 19 twenty 21 22 23 24 25
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int main() {    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 program has a serious logical error, 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 role exits. The GCC compiler is kind enough to result a warning (only non error).

It is safety to return a reference that is passed into the function as an argument. Run across earlier examples.

Passing Dynamically Allocated Memory equally Return Value by Reference

Instead, y'all need to dynamically classify a variable for the return value, and return it by reference.

one ii iii 4 5 6 7 8 9 ten eleven 12 xiii 14 15 16 17 18 xix 20 21 22 23
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int main() {    int number = viii;    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 circuitous and hard to main. But they tin greatly improve the efficiency of the programs.

For novices, avert using pointers in your program. Improper usage tin can pb to serious logical bugs. Notwithstanding, y'all demand to understand the syntaxes of pass-by-reference with pointers and references, because they are used in many library functions.

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

Dynamic Retentiveness Allocation

new and delete Operators

Instead of define 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 allocate a piece of retentiveness dynamically via new, y'all need to use delete to remove the storage (i.east., to return the storage to the heap).

The new operation returns a pointer to the memory allocated. The delete operator takes a arrow (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;        

Find that new and delete operators work on pointer.

To initialize the allocated retentivity, y'all tin use an initializer for fundamental types, or invoke a constructor for an object. For example,

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

Y'all can dynamically allocate storage for global pointers within a function. Dynamically allocated storage inside the role remains even subsequently the office exits. For example,

1 ii 3 iv v 6 vii viii ix 10 11 12 13 fourteen 15 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() {    classify();    cout << *p1 << endl;      cout << *p2 << endl;      delete p1;      delete p2;    return 0; }

The main differences between static resource allotment and dynamic allocations are:

  1. In static allocation, the compiler allocates and deallocates the storage automatically, and handle memory management. Whereas in dynamic allocation, you, as the programmer, handle the memory allocation and deallocation yourself (via new and delete operators). You accept full control on the pointer addresses and their contents, as well as memory 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, you need to utilise the delete[] operator (instead of only delete). For example,

i 2 3 4 five 6 7 viii nine 10 eleven 12 13 14 15 16 17 18 xix 20 21 22 23 24
                    #include <iostream> #include <cstdlib> using namespace std;   int chief() {    const int SIZE = v;    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 non let your to initialize the dynamically-allocated assortment. C++11 does with the caryatid initialization, as follows:

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

Arrow, Assortment and Part

Array is Treated as Arrow

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

For example,

i 2 3 4 5 6 vii viii 9 10 eleven 12 13 fourteen 15 sixteen
                    #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 + 1) << endl;       cout << *(numbers + iv) << endl;    }

Pointer Arithmetic

As seen from the previous section, if numbers is an int array, it is treated as an int arrow pointing to the commencement chemical element of the array. (numbers + 1) points to the next int, instead of having the next sequential address. Take notation that an int typically has iv bytes. That is (numbers + 1) increases the accost by 4, or sizeof(int). For example,

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

sizeof Array

The operation sizeof(arrayName) returns the total bytes of the array. You tin can derive the length (size) of the array by dividing information technology with the size of an chemical element (eastward.g. chemical 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 Office

An array is passed into a function every bit a pointer to the commencement element of the array. Yous can use array annotation (due east.g., int[]) or pointer note (east.thou., int*) in the function annunciation. The compiler ever treats information technology every bit pointer (e.g., int*). For example, the post-obit declarations are equivalent:

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

They volition be treated as int* past the compiler, as follow. The size of the assortment given in [] is ignored.

int max(int*, int);

Array is passed past reference into the function, because a pointer is passed instead of a clone copy. If the array is modified within the role, the modifications are applied to the caller'south copy. Y'all could declare the array parameter as const to forestall the array from being modified inside the part.

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

Instance: Using the usual array note.

one 2 iii 4 five 6 7 8 9 ten eleven 12 13 fourteen 15 16 17 xviii 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 print(const int arr[], int size);   int master() {    const int SIZE = 4;    int numbers[SIZE] = {xi, 22, 33, 22};    print(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 print(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 yous can modify the contents of the caller'south assortment inside the function, as assortment is passed by reference. To forestall accidental modification, yous could employ const qualifier to the function'due south parameter. Call back that const inform the compiler that the value should not be changed. For instance, suppose that the function print() prints the contents of the given array and does not modify the array, yous could utilise const to both the assortment name and its size, as they are not expected to be changed inside the role.

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

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

Example: Using arrow annotation.

1 2 3 4 five 6 7 8 9 10 11 12 13 xiv 15 16 17 xviii nineteen 20 21
                    #include <iostream> using namespace std;    int max(const int *arr, int size);   int main() {    const int SIZE = 5;    int numbers[SIZE] = {10, 20, 90, 76, 22};    cout << max(numbers, SIZE) << endl; }    int max(const int *arr, int size) {    int max =                  *arr;    for (int i = i; i < size; ++i) {       if (max <                  *(arr+i)) max =                  *(arr+i);    }    return max; }

Pass-past-Reference and sizeof

1 2 iii 4 v 6 vii 8 nine 10 xi 12 thirteen 14 15 xvi 17 18 xix xx 21
                    #include <iostream> using namespace std;    void fun(const int *arr, int size);    int primary() {    const int SIZE = 5;    int a[SIZE] = {8, iv, 5, three, 2};    cout << "sizeof in chief() is " <<                  sizeof(a)                  << endl;    cout << "accost 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 primary() is xx address in main() is 0x22fefc sizeof in function is 4 address in office is 0x22fefc

The address of arrays in main() and the function are the aforementioned, as expected, equally array is passed by reference.

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

Operating on a Range of an Array

i 2 three 4 5 vi 7 eight 9 x 11 12 xiii xiv 15 16 17 eighteen xix 20 21 22 23 24 25
                    #include <iostream> using namespace std;    int sum(const int *begin, const int *end);    int main() {    int a[] = {eight, 4, five, iii, 2, 1, 4, 8};    cout << sum(a, a+8) << endl;           cout << sum(a+two, a+5) << endl;         cout << sum(&a[ii], &a[five]) << endl;  }      int sum(const int *brainstorm, const int *finish) {    int sum = 0;    for (const int *p = begin; p != terminate; ++p) {       sum += *p;    }    return sum; }

Program Notes:

  • To write a function that operates on a range of the given array, you tin laissez passer the brainstorm pointer and the end pointer into the function. By convention, the performance shall start at the brainstorm pointer, up to the end pointer, only excluding the end pointer.
  • In "const int *p", *p (content pointed-to) is abiding, only p is not constant.

C-String and Pointer

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

ane two 3 4 v 6 vii viii ix x 11 12 13 14 fifteen xvi 17 xviii 19 20 21 22 23 24 25 26 27
                    #include <iostream> #include <cstring> using namespace std;   int main() {    char msg1[] = "Hello";    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 function such every bit strlen() (in header cstring, ported over from C'south string.h), there is no demand to pass the array length into the role. This is because C-Strings are terminated by '\0'. The function can iterate thru the characters in the array until '\0'. For case,

1 2 3 4 5 6 7 eight nine ten xi 12 13 14 fifteen xvi 17 18 19 20 21 22 23 24 25 26
                    #include <iostream> #include <cstring> using namespace std;   int count(const char *str, const char c);     int primary() {    char msg1[] = "How-do-you-do, world";    char *msg2 = "How-do-you-do, world";      cout << count(msg1, 'fifty') << endl;    cout << count(msg2, 'fifty') << endl;    cout << count("Hello, world", 'l') << endl; }     int count(const char *str, const char c) {    int count = 0;    while (*str) {          if (*str == c) ++count;       ++str;    }    return count; }

*More On Pointers

Role Pointer

In C/C++, functions, like all information items, have an accost. The name of a function is the starting address where the function resides in the retentivity, and therefore, can be treated as a arrow. We tin can pass a function pointer into part besides. The syntax for declaring a part pointer is:

            render-type          (*          function-ptr-name) (parameter-list)    double (*fp)(int, int)   double *dp;              double *fun(int, int)     double f(int, int);       fp = f;        
Example
one 2 iii four 5 6 vii 8 9 10 11 12 13 14 15 sixteen 17 xviii xix twenty 21 22 23 24 25
                    #include <iostream> using namespace std;   int arithmetic(int, int,                  int (*)(int, int));       int add together(int, int); int sub(int, int);   int add(int n1, int n2) { return n1 + n2; } int sub(int n1, int n2) { render n1 - n2; }   int arithmetic(int n1, int n2,                  int (*operation) (int, int)) {    return                  (*operation)(n1, n2); }   int primary() {    int number1 = five, number2 = half dozen;          cout << arithmetic(number1, number2, add) << endl;        cout << arithmetic(number1, number2, sub) << endl; }

Generic Pointer or void Arrow (void *)

A void arrow tin hold accost of any data type (except function pointer). We cannot operate on the object pointed to by void pointer, equally the blazon is unknown. We tin use a void arrow to compare with another accost.

[TODO] Example

Constant Pointer vs. Constant Pointed-to Data

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

Link to "C++ References & Resources"

bundymandes.blogspot.com

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

Post a Comment for "How to Read in a Char for a Double Function C++"