In the previous section, I have discussed about Built-in Data Types in depth.
Now, let's taste the flavors of Variables and literals, with a in depth introduction.
Variables
A Variable provide us with named memory storage, i.e. a storage in our so called RAM with a particular name (usually we give the name), We can write, modify and use this storage with the help of associated name (variable). Each variable in C++ is associated with some specific data type, like Built-in data types that we previously discussed.
There are mainly two values that are associated with any variable.
- RValues.
- LValues.
#include<iostream> using namespace std; int main() { int a = 10; cout << a << endl; // 10 is the RValue of a integer variable cout << &a << endl; // The LValue of a integer variable }
Literals
#include<iostream> using namespace std; int main() { int a = 10; // Decimal representation of integer literal 10 int b = 012; // Octal representation of integer literal 10 int c = 0xa; // Hexadecimal representation of integer literal 10 cout << "Value of a : " << a << endl; cout << "Value of b : " << b << endl; cout << "Value of c : " << c << endl; }
see output here. Here, I have shown you three different configurations for representing integer literals.
To tell the compiler that the value we providing is an octal number we write a preceding "0" to the number, and for the hexadecimal values we write preceding "0x" to the numbers.
( I have not written return 0 in the above program as my compiler (mingw) allow me to skip it in the main function/ but you should write and test in your compiler)
Now let's see some of the other literals that we use with modifiers.
#include<iostream> using namespace std; int main() { // Some example of integer literals long int a = 10L; // without L or l it will be treated as integer literal only. unsigned int b = 10U; // without U or u it will be treated as signed integer literal only. unsigned long int c = 10UL; // without UL or ul it will treated as signed integer only. // Some examples of float literal // I have given you example in the blog that 3.14 is double why? float x = 3.14; /* To make it a float literal F or f must be written like this 3.14F or 3.14f Otherwise, it will be treated as double only. */ return 0; }
If want to explore you can try to mix hexadecimal and octal with float and double.
Now, let's resume the things back again with Derived Data types.
Derived Data Types
- Array.
- Function.
- Pointer.
- References.
syntax of array - <datatype> <name>[<size of array>];
#include<iostream> using namespace std; int main() { /* You can define arrays of any data type you want */ char alphabets[26] = {'a','b','c','d','e','f','g','h','i', // Array of data type character 'j','k','l','m','n','o','p','q','r','s', 't','u','v','w','x','y','z'}; /* I defined all alphabets using single name But without array we could have used 26 different names which is a tiring task */ return 0; }
The below program 3 ways of declaring an array.
#include<iostream> using namespace std; int main() { int array1[10]; // By mentioning the size of the array. int array2[] = {1,2,3,4,5,6,7,8,9,10}; // By giving the elements directly int *array3 = new int[10]; // Array is created in heap memory. return 0; }
(new is an operator used for dynamic allocation, we will see it in pointers too).
Till now, we just have seen 1d array i.e. a linear array. But in c++ you can define arrays of any dimension, You can relate 2 dimensional array like int array[n][m]; with a matrix of n rows and m columns. Below is a small example.
#include<iostream> using namespace std; int main() { int Array2[2][2] = { // 2 dimensional array {1, 2}, {3, 4} }; int Array3[2][2][2]; // 3 dimensional array return 0; }
Important Note - Actually it does not matter what are the dimensions of the array, it still occupies contiguous memory locations.
2. Function - Functions can be considered as a block of a program in which there is a mixture of loops, statements and logics is present to perform a task, The main criteria of using a function is that we can use a defined function any number of time as we want, or we can include them in our own separate header file and use those function in some other ".cpp" files..
Syntax of a function - <return type> <name of function> (parameters){ body }
Now, this syntax is looking little scary so let's take an example of a function which gives us the maximum of 3 numbers.
#include<iostream> using namespace std; int findingMax(int a, int b, int c) { if(a >= b && a >= c) // If "a" is greater than both "b" and "c" then "a" is greatest { return a; // return value of "a" if above condition is true } if(b >= c) return b; /* if above condition is false than it means "a" must not be the greatest so we can exclude that */ return c; /* If we have not found maximum till now just return "c" */ } int main() { int a = 10; int b = 20; int c = 15; int d = findingMax(a,b,c); cout << d << endl; return 0; }
See, results here.
Here we have written two functions one is findingmaxi() and another in main() function. Till now we just know that main() is the most important function.
Now, let's talk about what is actually happening, In main function we defined three variables "a", "b" and "c" with some values, and an integer "d" which is assigned to findingMax(a,b,c);,
Here, in int d = findingMax(a,b,c); the findingMax is the name of the function and "a", "b" and "c" are parameters or actual arguments that we sent provide to over function, Now, we go the definition of our findingMax() function, Here the function is written as
int findingMax(int a, int b , int c){}, here int is the return type of this function i.e. when it, executes it return a value of type integer, which in turn is stored in variable "d" in main function. Parameter written during definition, must be provided with their data types as well. The parameters, we write during definition are referred to as formal parameters or arguments. After that whole logic is written inside the curly braces.
Please, try your best to understand the logic so that you get some pump.
#include<iostream> using namespace std; void findingMax(int a, int b, int c) { if(a >= b && a >= c) { cout << a << endl; return; } if(b >= c) { cout << b << endl; return; } cout << c << endl; } int main() { int a = 10; int b = 20; int c = 15; findingMax(a,b,c); return 0; }
See execution here.
If you look the output we got is same. But the difference is here is void does not returning anything to the main function, i.e. whatever, happening in findingMax does not provide any knowledge to main.
3. Pointers - Pointer is exactly the same things as it is named. Pointer points to the address of some other object (not necessarily a variable). Ok, but, what is the need of pointers?
Pointers are extensively used in the application of data structures like linked list, trees etc.( We will cover them after we complete our c++ tutorial). Pointers are used to dynamically allocate memory, Pointer are also used to indirectly manipulate objects which are assigned to them
Now, what does this mean.
Till now we have seen that we can declare variables by just writing data types and and names, but those variables that we create are called automatic variables because they are automatically allocated and de-allocated through the stack - memory, but wait we have still not used our heap memory, what if we can utilize that space also, Yes, We can utilize it also by the help of pointers and new operator or in C we use malloc() function.
But, wait, there's a fact that we can't directly access the variable present in heap memory, through our program,(What?😕), We can't access them directly but, Yes we can access them indirectly, otherwise just creating them doesn't make any sense. We can access them with the help of pointers i.e. we can store the address of the heap memory objects in our pointers and just by using them we can directly reach to that memory address. Now, As we are accessing pointers directly, it must be clear in our mind that pointer in this example is present in our stack memory, It can present in heap also but then we need one more pointer to point to heap memory pointer, i.e. pointer to a pointer.
Syntax - <data type> *<name>;
Let's see a program on pointer to an object.
#include<iostream> using namespace std; int main() { int b = 10; // automatic variable in stack memory int *a; // It is automatic too a = &b; // "a" points to the address of b, but both are present in stack only. int *c = new int; // with new we create objects in heap . *c = 123; // To find out the address of a pointer we dereference it or simply // Write it down by removing one of its preceeding (*); // And to find out address of a stack variable we simply use ampersand. // Remember a is equal to address of b here. (watch output) cout << "Address of b is : " << &b << endl; cout << "Address of *a : " << a << endl; cout << "Address of c : " << c << endl; delete c; return 0; }
For accessing the address of an variables we use ampersand in front of it. like I did when I am assigning the address of "b" to pointer "a" and while printing it too.
You can even create arrays (or anything you want) in heap memory like this.
int *array = new int[size];
but make sure to delete the it when it is not in use, for deleting an array write delete[] <name>;
We will discuss pointer arithmetic and use of pointers in parameter passing in later slides.
4. References - References, sometimes referred to as an alias, because, these serves as an alternative name for the other objects. Just like pointers, these are also used to indirectly manipulate the object but the syntax is bit different. Application of references are we can pass parameters by reference, overloading of operators etc.
Syntax - < datatype > &<name> = <Rvalue>
Important things to be remembered -
- RValues is nothing but another object and must be of the same type of the reference object (except for const references).
- Once a reference is defined to one object it cannot be referenced to any other object. Yes the value of the object to which it is referencing can change.
- A reference must be initialized in the same step, where it is declared.
#include<iostream> using namespace std; int main() { int a = 10; // double &x = a; // Wrong const double &x = a; // Right int b = 10; int c = 20; int &d = b; // d is referencing to b d = c; // The value of bs change but d will still reference to b return 0; }
Actually, the line double &x = a; and const double &x = a; are both not correct as but const double &x = a; will not generate compilation error because, there is an implicit conversion working here, and these conversion takes place in two steps -
- double temp = a; assigning the value of "a" to any temporary variable.
- const double &x = temp; referencing to that particular temporary variable.
which means x is not referencing on a itself but rather a temporary object that is created by compiler implicitly(internally without our knowledge). But, it is only possible when there is a conversion between two datatypes is applicable for example if you try to reference a double type to a string type, you will get invalid reference error.
This, is sufficient for now, I will be discussing more of these derived types in later slides.
In next slide we will discuss the User Defined Data Types.😊
Stay tuned for the upcoming content. For any query leave a comment below.
- Wikipedia.
- hilite.com for code snippets.
- ideone.com
Comments
Post a Comment