C++ Programming Series: Pointers (Part 2)

In the previous post, we learned how to get the memory address of a variable and how to define a variable that holds the memory address i.e pointer.

Suppose that there is a variable of type int called number. We initialize it with value equals to 10. Now, suppose that it has a memory address 091 (Sounds ridiculous but it’s just a supposition). This memory address is present somewhere in our device’s memory.

Some of the memory addresses are shown in the table below, along with the values present in each.

Address 090 091 092 093 094 095
Value Garbage number number number number Garbage

Now, we know that number has a memory address 091. Then, why 092, 093 and 094 are also filled with value, number? Well, just think a little on why not 095? 095 is just a garbage value!

Okay, okay! Let me clear this confusion. number is of type int and the size of int is 4 bytes. Each memory address carries 1 byte. Therefore, to fit a variable of type int, it requires 4 neighboring memory addresses.

So, number is having memory addresses, 091, 092, 093 and 094. But the only memory address that is useful to us, is the first one i.e 091. Every variable only knows its first memory address and its size. When we know the first memory address of a variable, we can easily get the value of that variable.

Now, suppose that we have a pointer of type int called pNumber. We initialize it with the memory address of the number (How to get memory address of a variable? By putting ampersand(&) behind it).

Now, the pNumber is also 091. We dereference it (i.e we put an asterisk(*) behind the pNumber) to get the value 10.

Actually, when we dereference the pointer, we are actually, looking up the memory address which in this case, is 091. Pointer of type int will suggest that whatever is present in this memory address will be the starting byte of the variable which is of type int.

Please read the above statement twice! It is a bit tricky!

To make it easy, here’s the same table:

Address 090 091 092 093 094 095
Value Garbage number —–> pNumber number number number Garbage

After looking up the memory address, pointer takes the value which in this case, is 10.

If you try sizeof() for pointer of any type, it will tell you that the size of pointer is 8 bytes (or may be different depending on your device). This is because a pointer consists memory address and memory address is a hexadecimal value. Hexadecimal values are big values! Therefore, every pointer resembles to type long int which is also 8 bytes in size.

We can manipulate with the pointers as well. We will discuss it in the upcoming posts in detail. For now, just get along with pointers and the concept described above. It should not be hard now! There is still a huge ground to cover regarding pointers…

C++ Programming Series: Multidimensional Arrays

In the last two previous posts, we discussed a very useful thing called as ‘Arrays’. This topic is not yet completed and this post is going to end it! Multidimensional arrays!

Previously, we discussed 1D (or single dimensional) arrays. They are pretty simple.

int arr[10];
arr[0] = 2;
arr[3] = 10;
arr[7] = 40;
//arr[10] is not possible, will give error!
cout << arr[0] + arr[3] + arr[7] << endl; //Outputs 52

But now, time for 2D and 3D arrays. We won’t go in details with 3D because they are like 2D, understanding 2D array will give us the understanding of 3D arrays as well. Also, 3D arrays are rarely used.

int arr1d[3] = {1, 2, 3};

int arr2d[3][3] =
{
  {1, 2, 3},
  {4, 5, 6},
  {7, 8, 9}
};

int arr3d[3][3][3] =
{
  {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
  },
  {
    {10, 11, 12},
    {13, 14, 15},
    {16, 17, 18}
  },
  {
    {19, 20, 21},
    {22, 23, 24},
    {25, 26, 27},
  }
};

cout << "1D Array:-\n";
for (int x = 0; x < 3; x++)
  cout << arr1d[x] << " ";
cout << endl;

cout << "2D Array:-\n";
for (int y = 0; y < 3; y++)
{
  for (int x = 0; x < 3; x++)
  {
    cout << arr2d[y][x] << " ";
  }

  cout << endl;
}

cout << "3D Array:-\n";
for (int z = 0; z < 3; z++)
{
  for (int y = 0; y < 3; y++)
  {
    for (int x = 0; x < 3; x++)
    {
      cout << arr3d[z][y][x] << " ";
    }

    cout << endl;
  }

  cout << endl;
}

Dimensions are increased by putting another pair of square brackets. Number of elements in a multidimensional array will be the product of the values in each pair of square brackets that are typed in during the initialization of that array. For example, in the above cases, arr2d has 9 elements and arr3d has 27 elements. Below is how you can access elements of arr2d, individually.

//cout << arr2d[0][3] << endl; Gives error or garbage value
cout << arr2d[0][2] << endl; //Outputs 3
//cout << arr2d[3][0] << endl; Gives error or garbage value
cout << arr2d[2][0] << endl; //Outputs 7
cout << arr2d[1][1] << endl; //Outputs 5 (middle element)
cout << arr2d[2][2] << endl; //Outputs 9 (last element)
cout << arr2d[1][2] << endl; //Outputs 6
cout << arr2d[2][1] << endl; //Outputs 8

Remember, array index number starts from 0 and not 1. The concept behind multidimensional arrays, is the fact that each 2D array consists of 1D arrays, which contain elements and so, each 3D array consists of 2D arrays, which further, consists of 1D arrays, which contain elements. I know that sounds complicated!

//Number of 1D arrays present in the 2D array
//is the number typed in the 1st pair of square brackets
int arr2d_2[1][3] =
{
	{ 1, 2, 3 } // -> Only one 1D array in a 2D array
};

The tricky question is, how to access all elements of a multidimensional arrays with sizeof()? It is pretty simple but tricky! Simply, to get the total number of sub-arrays or max index value of first pair of square brackets, divide the memory size of whole multidimensional array with the memory size of sub-array. And then, to get the total number of elements in each sub-array, divide the memory size of a sub-array with the memory size of an element.

string machines[2][4] =
{
  { "Calculator", "Computer", "Printer", "Scanner" },
  { "Microwave Oven", "Blender", "Refrigerator", "Juicer" }
};

//Memory size of whole array: sizeof(machines)
//Memory size of sub-array: sizeof(machines[0])
//Memory size of element: sizeof(machines[0][0])

//Total number of elements = sizeof(machines) / sizeof(machines[0][0])

//sizeof(machines) / sizeof(machines[0]) = 2
for (int y = 0; y < sizeof(machines) / sizeof(machines[0]); y++)
{
  //sizeof(machines[0]) / sizeof(machines[0][0]) = 4
  for (int x = 0; x < sizeof(machines[0]) / sizeof(machines[0][0]); x++)
  {
    cout << machines[y][x];

    //To avoid putting comma after the last element of each sub-array
    if (x != (sizeof(machines[0]) / sizeof(machines[0][0])) - 1)
      cout << ", ";
  }
  cout << endl;
}

I am pretty sure that it is complex. But if you code and practice on your own, you will found it to be easy! The good thing about 2D arrays is the fact that you can manage data in the form of tables! Try to make a table of numbers ranging from 0 to 100 where each sub-array or 1D array in the 2D array, will have 10 elements. It will be better if you use sizeof() for outputting the table.

That’s all! I hope you got it all right!

C++ Programming Series: Precedence, Order and sizeof()

In the previous post, we learned complex but still, simple looking conditions.

Instead of using boolean variables for complex conditions, we can directly use them in the conditional statements. Below is an example of a ‘complex looking’ complex condition:

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

if( b == a + a || a == c - b && b != c - a && c > a )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

Now, guess the output without executing it (or running it). It looks hard or complex to tell whether it is true or false. Actually, this will run in a specific order due to difference in the precedence. Precedence is the priority to check or run something in a statement. The precedence of AND logical operator(&&) is more than that of OR logical operator(||) which means that first, all AND logical operators will get executed and then, at last, the OR logical operator. The position do not justify the precedence; it is a property of an operator having a specific value.

Precedence helps to reduce errors. But it may be possible that programmer don’t want the order of execution in accordance with the precedence. The precedence factor can be overwritten with the use of round brackets. Following code shows the order of running or executing code due to precedence, using round brackets:

if( (b == a + a || (a == c - b && b != c - a && c > a)) )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

The inner round brackets run before the outer ones. If there is only a pair of round brackets, it will run before all other code. This is how, precedence decides it to run. And the output is, “True!”. Now, below is the overwritten precedence order using round brackets:

if( ( (b == a + a || a == c - b) && b != c - a) && c > a )
{
  cout << "True!" << endl;
}
else
{
  cout << "False!" << endl;
}

In the above code, the OR logical operator will be executed first. The change in precedence is clear as the output, this time, is “False!”.

Same is the case with the arithmetic operators i.e +, -, /, *, %, ++, –, and all other operators. Here is C++ Operator Precedence Table (There are many operators that we don’t know yet! It will be helpful in future as well.)

In the post of Primitive Types, we learned types which have different memories. Sometimes, using lesser memory is a good thing and optimizes the program. How can we know the amount of memory allocated (or used) by a type or a variable? The sizeof() operator is for this purpose.

float i_am_float = 10.99f;
double i_am_double = 99.101010;

//sizeof() will return the amount of memory allocated by the type or variable, mentioned in the round brackets.
cout << sizeof(long long int) << endl;
cout << sizeof(char) << endl;
cout << sizeof(i_am_float) << endl;
cout << sizeof(i_am_double) << endl;
cout << sizeof(double) << endl; 
cout << sizeof(string) << endl; //Non-primitive type. Remember, to include string

The memory allocated by the type is not universal for all platforms and IDEs (like Visual Studio).

We will see later on, how important precedence and sizeof() is, to our programming. But for now, just do as many experiments as possible with the precedence thing. Try 2+2-2/2*2 or something like that! Try 2+value++! Just keep trying until you reveal the precedence of the operators you know at that time. Then, get the output of the above sizeof() code.

Programming is something, boring before and interesting after learning!