Saturday, April 19, 2025

C++ References

Think about a reference as aliase for a variable. To have a reference, first variable must be created, for example:

int var = 5555;

Now pointer to a variable:

int *ptrVar = &var;

And now reference to variable using ampersand symbol between data type and reference name:

int & varRef = var;

Knowing pointers and references, we can get value in a variable:

cout << "Value in var: " << var << endl;
cout << "Value using pointer: " << *ptrVar << endl;

cout << "Value using Reference: " << varRef << endl;

Full script: 

#include <iostream>

using namespace std;

int main() {

    int var = 5555;
    int *ptrVar = &var;

    int & varRef = var;

    cout << "Value in var: " << var << endl;
    cout << "Value using pointer: " << *ptrVar << endl;

    cout << "Value using Reference: " << varRef << endl;

    return 0;

}

Result:

Value in var: 5555
Value using pointer: 5555
Value using Reference: 5555

Process returned 0 (0x0)   execution time : 0.215 s
Press any key to continue.

C++ Pointers to Pointer

Yes, with a C++ we have a lot of options.

One of them is to have pointers pointing to pointers.

To simplify explanation, it's memory address where as real value we have another memory address.

Pointer to pointer is created using this symbol: "**".

First initial variable, for example, integer:

int Number = 5000;

Then pointer to variable:

int *primPtr;

Then pointer to pointer:

int **secPtr;

First pointer targets original variable:

primPtr = &Number;
cout << "Address of actual Variable: " << primPtr << endl;

Second pointer targets first pointer:

secPtr = &primPtr;
cout << "Address of Address: " << secPtr << endl;

And now fun stuff - we can get real value using variable, first or second pointer: 

cout << "Actual Value - direct from Variable: " << Number << endl;
cout << "Actual Value - using prim. pointer: " << *primPtr << endl;
cout << "Actual Value - using sec. pointer: " << **secPtr << endl;

Full script: 

#include <iostream>

using namespace std;

int main() {

    int Number = 5000;
    int *primPtr;
    int **secPtr;

    primPtr = &Number;
    cout << "Address of actual Variable: " << primPtr << endl;

    secPtr = &primPtr;
    cout << "Address of Address: " << secPtr << endl;

    cout << "Actual Value - direct from Variable: " << Number << endl;
    cout << "Actual Value - using prim. pointer: " << *primPtr << endl;
    cout << "Actual Value - using sec. pointer: " << **secPtr << endl;

    return 0;

}

Result:

Address of actual Variable: 0x6dfee8
Address of Address: 0x6dfee4
Actual Value - direct from Variable: 5000
Actual Value - using prim. pointer: 5000
Actual Value - using sec. pointer: 5000

Process returned 0 (0x0)   execution time : 0.075 s
Press any key to continue.

C++ Array of Pointers

For every element in array, we can have an individual pointer.

Just as in last example where we listed elements and pointers, for loop will be used here.

First array of integers is created:

int myArr[3] = {55, 66, 77};

Then we state a need for Array of Pointers that will hold three memory addresses:

int *arrPtr[3];

Finally a for loop is used to list all of them:

 for (int x = 0; x < 3; x = x + 1) {
        arrPtr[x] = &myArr[x];
        cout << "Address: " << arrPtr[x] << endl;
        cout << "Value: " << *arrPtr[x] << endl;
    }

Please note that with this line we are aligning an individual pointer to individual value from our original array: 

arrPtr[x] = &myArr[x];

Full source: 

#include <iostream>

using namespace std;

int main() {

    int myArr[3] = {55, 66, 77};
    int *arrPtr[3];

    for (int x = 0; x < 3; x = x + 1) {
        arrPtr[x] = &myArr[x];
        cout << "Address: " << arrPtr[x] << endl;
        cout << "Value: " << *arrPtr[x] << endl;
    }

    return 0;

}

Result:

Address: 0x6dfee0
Value: 55
Address: 0x6dfee4
Value: 66
Address: 0x6dfee8
Value: 77

Process returned 0 (0x0)   execution time : 0.056 s
Press any key to continue.

C++ Looping through Array using Pointers

We can use for loop in combination with pointers to get real values from arrays.

First we will create integer array with three elements:

int myArr[3] = {55, 66, 77};

Then NULL pointer is created:

int *ptrMyArr = NULL;

Then we connect a pointer and array:

ptrMyArr = myArr;

We have for loop extracting individual elements using pointers.

for (int x = 0; x < 3; x = x + 1) {
        cout << "Address ATM: " << ptrMyArr << endl;
        cout << "Value ATM: " << *ptrMyArr << endl;

        ptrMyArr = ptrMyArr + 1;
    }

Please note, because we use pointers we must jump from one memory address to another using this line in for loop:

ptrMyArr = ptrMyArr + 1;

Full script: 

#include <iostream>

using namespace std;

int main() {

    int myArr[3] = {55, 66, 77};
    int *ptrMyArr = NULL;

    ptrMyArr = myArr;

    for (int x = 0; x < 3; x = x + 1) {
        cout << "Address ATM: " << ptrMyArr << endl;
        cout << "Value ATM: " << *ptrMyArr << endl;

        ptrMyArr = ptrMyArr + 1;
    }

    return 0;

}

Result:

Address ATM: 0x6dfedc
Value ATM: 55
Address ATM: 0x6dfee0
Value ATM: 66
Address ATM: 0x6dfee4
Value ATM: 77

Process returned 0 (0x0)   execution time : 0.065 s
Press any key to continue.

C++ Null Pointer

To realize why NULL Pointers are useful, furst run this code to print junk value at memory location.

Junk value means we are dealing with values that are leftovers from previous operations: 

#include <iostream>

using namespace std;

int main() {

    int *somePointer;

    cout << "Address: " << somePointer << endl;

    cout << "Garbage Value: " << *somePointer << endl;

    return 0;

}

Result:

Address: 0x4270ce
Garbage Value: 1528349827

Process returned 0 (0x0)   execution time : 0.021 s
Press any key to continue.

Bottom line, we never intentionally pushed 1528349827 at memory location 0x4270ce. 

Let's play with a pointer pointing to values of different data types:

#include <iostream>

using namespace std;

int main() {

    int *somePointer;
    float *anotherOne;
    double *someMore;

    cout << "Address: " << somePointer << endl;
    cout << "Address: " << anotherOne << endl;
    cout << "Address: " << someMore << endl;

    cout << "Garbage Value: " << *somePointer << endl;
    cout << "Garbage Value: " << *anotherOne << endl;
    cout << "Garbage Value: " << *someMore << endl;

    return 0;

}

Result:

Address: 0x4271be
Address: 0x6dff80
Address: 0x427160
Garbage Value: 1528349827
Garbage Value: 1.01019e-038
Garbage Value: -1.39062e-284

Process returned 0 (0x0)   execution time : 0.064 s
Press any key to continue.

And now we will use NULL Pointer to evade possibility of using junk values: 

#include <iostream>

using namespace std;

int main() {

    int *somePointer = NULL;
    float *anotherOne = NULL;
    double *someMore = NULL;

    cout << "Address: " << somePointer << endl;
    cout << "Address: " << anotherOne << endl;
    cout << "Address: " << someMore << endl;

    cout << "Garbage Value: " << *somePointer << endl;
    cout << "Garbage Value: " << *anotherOne << endl;
    cout << "Garbage Value: " << *someMore << endl;

    return 0;

}

Result:

Address: 0
Address: 0
Address: 0

Process returned -1073741819 (0xC0000005)   execution time : 0.675 s
Press any key to continue.

C++ Change Variable with Pointer

We can change value in original variable using pointers, and pointers are just memory address where we have real value.

First we are creating an original variable and directly printing it:

int Number = 4323;
cout << "Original Value Atm: " << Number << endl;

Then a pointer is created and memory address printed:

int *ptrNumber = &Number;
cout << "Actual Address: " << ptrNumber << endl;

Then new value for original variable is set USING pointer (we use "*" symbol here)

*ptrNumber = 10000;

And now we can dereference a pointer to get value:

cout << "Value After Change: " << *ptrNumber << endl;

Or we can print value directly using original variable name: 

cout << "Value in Container (Variable): " << Number << endl;

Full script: 

#include <iostream>

using namespace std;

int main() {

    int Number = 4323;
    cout << "Original Value Atm: " << Number << endl;

    int *ptrNumber = &Number;
    cout << "Actual Address: " << ptrNumber << endl;

    *ptrNumber = 10000;
    cout << "Value After Change: " << *ptrNumber << endl;
    cout << "Value in Container (Variable): " << Number << endl;

    return 0;

}

Result:

Original Value Atm: 4323
Actual Address: 0x6dfee8
Value After Change: 10000
Value in Container (Variable): 10000

Process returned 0 (0x0)   execution time : 0.062 s
Press any key to continue.

C++ Dereferencing a Pointer

We learned that a pointer is variable that holds memory address of some real variable that holds value.

Now, dereferencing means that we will get VALUE of ORIGINAL variable using memory address.

First, we will create original variable PI, data type is float. Value is 3.14.

float PI = 3.14;

Then, we are creating a pointer that will provide us memory address of an original variable.

float *ptrPI = &PI;

Ok, now we have both value and pointer set up. 

That means we can dereference a pointer to get original value:

And we can get a pointer itself, which is just memory address of original value.

Please note, we ARE NOT using original variable name to get real original data (3.14). ALL the time we are using pointers:

#include <iostream>

using namespace std;

int main() {

    float PI = 3.14;
    float *ptrPI = &PI;

    cout << "Actual Value In That Address: " << *ptrPI << endl;
    cout << "Actual Address: " << ptrPI << endl;

    return 0;

}

Result:

Actual Value In That Address: 3.14
Actual Address: 0x6dfee8

Process returned 0 (0x0)   execution time : 0.077 s
Press any key to continue.

Perhaps it's weird that we are using symbol "*" two times here.

But first time we use it to CREATE a pointer and second time to DEREFERENCE pointer so we can get ORIGINAL value from a memory address.

Pointers and Constants

We can play around with constants too. They are created above main() section.

If a constant is of data type string (for example), a pointer must be also of same data type.

Once we have a pointer, we can print it to get memory address, or we can dereference it (using "*" symbol)  to get real value in ORIGINAL constant.

You will get used to pointers in C++, don't worry.

#include <iostream>

using namespace std;

const string STR = "Slavoj Zizek vs J.Peterson";

int main() {

    const string *ptrSTR = &STR;

    cout << "Actual Address: " << ptrSTR << endl;
    cout << "Actual Value: " << *ptrSTR << endl;

    return 0;

}

Result:

Actual Address: 0x4c600c
Actual Value: Slavoj Zizek vs J.Peterson

Process returned 0 (0x0)   execution time : 0.056 s
Press any key to continue.

C++ Pointer Declaration Conventions

 While naming pointers we generally have two approaches.

After data type and pointer symbol "*", for a name we can start with a lowercase letter and concatenate it with a uppercase letter.

Another variant is start with uppercase letter and continue with uppercase letter.

In first option we can start with ptr as prefix, and in second option ptr will be suffix for pointer name.

Just make sure that pointer name describes clearly where it is pointing.

Just stick to one approach that works for you:

#include <iostream>

using namespace std;

int main() {

    int number = 1000;

    int *ptrNumber = &number;
    int *NumberPtr = &number;

    cout << ptrNumber << endl;
    cout << NumberPtr << endl;

    return 0;

}

Result:

0x6dfee4
0x6dfee4

Process returned 0 (0x0)   execution time : 0.126 s
Press any key to continue.

C++ gives you freedom to use a pointer symbol "*" in three ways. Use one that looks "clearer" to you.

A lot of discussions exist on internet about which way is correct, but just make sure that you use one approach you like all the time.

#include <iostream>

using namespace std;

int main() {

    int number = 1000;

    int *ptrNumber = &number;
    int * ptrNumber2 = &number;
    int* ptrNumber3 = &number;

    cout << ptrNumber << endl;
    cout << ptrNumber2 << endl;
    cout << ptrNumber3 << endl;

    return 0;

}

Result:

0x6dfee0
0x6dfee0
0x6dfee0

Process returned 0 (0x0)   execution time : 0.049 s
Press any key to continue.

C++ Pointers Explained

Pointers are easy.

A pointer is a variable, but it stores the memory location (address) of real value we provide in some other variable.

They are like real GPS coordinates of some house. Yes, we need to know real street number of some house, but pointers are more like GPS coordinates.

You can think about them as excel table where combination of a row and column will tell us real value in that cell.

Except we are talking about real memory chips here, hardware location of values.

Of course, hardware locations are fixed, but values in them (just as in Excel cells) can change.

So, it's easy to get any value just knowing exact memory location (we have just printed location here, pointer creation will be explained too):

#include <iostream>

using namespace std;

int main() {

    int number = 1000;

    cout << "Actual value: " << number << endl;

    cout << "Address of container for number: " << &number << endl;

    return 0;

}

Result:

Actual value: 1000
Address of container for number: 0x6dfeec

Process returned 0 (0x0)   execution time : 0.344 s
Press any key to continue.

So far so good.

Now we will create a pointer that will point to memory location we printed above:

On left side of pointer name we must have data type same as value data type and special "*" symbol for pointers.

Once we create a pointer, there is no need to use "*" symbol while using a pointer to print memory location:

#include <iostream>

using namespace std;

int main() {

    int number = 1000;

    cout << "Actual value: " << number << endl;
    cout << "Address of container for number: " << &number << endl;

    int *pointer_to_number = &number;

    cout << pointer_to_number << endl;

    return 0;

}

Result:

Actual value: 1000
Address of container for number: 0x6dfee8
0x6dfee8

Process returned 0 (0x0)   execution time : 0.182 s
Press any key to continue.
Don't worry if you don't understand pointers at the moment, give yourself a little bit of time.

C++ Constants - #define

Another simple way to create constants is to use #define preprocessor.

Again #define section must be above main() section, just as when we were using "const" keyword.

The important thing here is that there is no need to use "=" symbol between a constant name and value we provide.

It's very simple and clean solution: 

#include <iostream>

using namespace std;

#define PI 3.14
#define CAR 'Y'
#define STR "This is some string"
#define HEAD_LINE "------------------------"

int main() {

    cout << HEAD_LINE << endl;

    cout << PI << endl;
    cout << CAR << endl;
    cout << STR << endl;

    cout << HEAD_LINE << endl;

    return 0;

}

Result:

------------------------
3.14
Y
This is some string
------------------------

Process returned 0 (0x0)   execution time : 0.182 s
Press any key to continue.

C++ Constants - const

Constants represent fixed values if we know in advance that there's no need to change them during program execution.

As with variables, they can be of any data type. They are extremely useful when we know what type of "inputs" are fixed in time.

They must be defined above main() section of our program.

One way to do that is to use keyword "const" on far left side than data type than name for a constant and finally, their value.

As with any instruction in C++, semicolon must be used at the end of lines dedicated for constants: 

#include <iostream>

using namespace std;

const float pi = 3.14;
const char let = 'Z';
const int vol_lev = 5;
const string head_line = "-------------------------";

int main() {

    cout << head_line << endl;
    
    cout << "PI Value: " << pi << endl;
    cout << "Letter: "   << let << endl;
    cout << "Voltage: "  << vol_lev << endl;
    
    cout << head_line << endl;

    return 0;

}

Result:

-------------------------
PI Value: 3.14
Letter: Z
Voltage: 5
-------------------------

Process returned 0 (0x0)   execution time : 0.114 s
Press any key to continue.

C++ Elements from Multidimensional Array

To list all elements from a multidimensional array in C++ (two rows, three columns) we can use a combination of for loops.

Basically, we will have for loop inside for loop.

External for loop will be dedicated to list lines, and internal for loop will handle columns.

While combining all positions horizontally and vertically we will get all individual elements printed.

Every time when we print an element, tab is added to the right side. In such way spacing is preserved so that elements are not concatenated while printing them.

Run this code and experiment with it: 

#include <iostream>

using namespace std;

int main() {

    int multiArr[2][3] = {{2, 5, 6}, {4, 7, 9}};

    for (int row = 0; row < 2; row = row + 1) {

        for (int col = 0; col < 3; col = col + 1) {
            cout << multiArr[row][col] << "\t" ;
        }
        cout << endl;
    }

    return 0;

}

Result:

2       5       6
4       7       9

Process returned 0 (0x0)   execution time : 0.021 s
Press any key to continue.

C++ Comments

Comments in programming can be short or simple explanations what specific source code do.

We use them to explain ourselves and our colleagues what our code is doing because someone (including us) can read comments/source even decades after programs is completed.

Usually, it's smart idea to keep comment short and to the point.

Comments will not influence execution of source code, they will just sit there if we need to read them.

Authors of programming languages have different symbols to start and end comment section, and in C++ we use // to star one line comment, and /* and */ pair to start and end multiline comment section.

Comments are useful because we can write programs that will get into our other programs and extract comments as documentation.

We can transfer/extract that internal "documentation" in different formats, HTML, pdf, txt and so on, if needed. 

#include <iostream>

using namespace std;

int main() {

    int multiArr[2][3] = {{2, 5, 6}, {4, 7, 9}};

    //This is First One Line Comment

    //This code down there will not run, it's multiline comment section

    /*
    cout << multiArr[0][0] << endl;
    cout << multiArr[0][1] << endl;
    */

    //This is Second One Line Comment

    cout << "This will be printed" << endl;
    cout << "This too: " << multiArr[0][2] << endl;

    return 0;

}

C++ Multidimensional Arrays

 The best way to understand multidimensional arrays is with the simplest possible example.

In this case name for our multidimensional array is multiArr[][]. We must use two square brackets because our array will have two lines and three elements in each line.

To populate array of this type for every line of elements we have individual curly brackets separated by a comma.

To extract elements, we will use positions

Position 0 will target the first line. Position 1 will target the second line of elements.

Inside any of these lines with elements we can target individual elements using positions 0, 1, 2 because we have a total of three elements in each line, but in C++ we start counting from position 0.

Run this code:

#include <iostream>

using namespace std;

int main() {

    int multiArr[2][3] = {{2, 5, 6}, {4, 7, 9}};

    cout << "Elements from First Array: " << endl;
    cout << multiArr[0][0] << endl;
    cout << multiArr[0][1] << endl;
    cout << multiArr[0][2] << endl;

    cout << "----------------------------------" << endl;

    cout << "Elements from Second Array: " << endl;
    cout << multiArr[1][0] << endl;
    cout << multiArr[1][1] << endl;
    cout << multiArr[1][2] << endl;

    return 0;

}

Result:

Elements from First Array:
2
5
6
----------------------------------
Elements from Second Array:
4
7
9

Process returned 0 (0x0)   execution time : 0.076 s
Press any key to continue.

C++ Arrays in Functions

We can use array as function argument. For example, function printElement() will have task printing specific element using positions/indexes.

Our function will take two parameters, first will be our array of integers, and second will be position of some element.

Of course, declaration of the function will be done before main() section of the program.

We are using genArr[] as generic/abstract name for any real array we pass, and integer posOfElem will represent any position of an element we need, because we can use this function multiple times, on multiple different arrays.

Our real array "numbers" with real values is in main() section. We have five elements total, and searching for value at position four, in this example: 

#include <iostream>

using namespace std;

void printElement(int genArr[], int posOfElem) {
    cout << "Element of array: " << genArr[posOfElem] << endl;
}

int main() {

    int numbers[5] = {23, 34, 56, 5000, 2};

    printElement(numbers, 4);

    return 0;

}

 Result:

Element of array: 2

Process returned 0 (0x0)   execution time : 0.137 s
Press any key to continue.

An absolutely same approach when we are working with arrays that store other data types.

In this example we have array of characters, so our first parameter for function will be generic array g[], and second parameter integer "x" will represent position of some element we care about when function is called.

Don't forget single quotes around elements, because we are working with individual characters and not strings (words).

Run this code: 

#include <iostream>

using namespace std;

void printElement(char g[], int x) {
    cout << "Element of array: " << g[x] << endl;
}

int main() {

    char simbols[3] = {'A', 'C', 'D'};

    printElement(simbols, 1);

    return 0;

}

Result:

Element of array: C

Process returned 0 (0x0)   execution time : 0.157 s
Press any key to continue.

Tkinter Introduction - Top Widget, Method, Button

First, let's make shure that our tkinter module is working ok with simple  for loop that will spawn 5 instances of blank Tk window .  ...