Learning

Most of the times we start to learn programming in C, we try to master it and then dive into C++, which is a little bit time taking process and sometimes we feel like its a long way to go before we jump on to C++, isn’t it ?

since C has became a subset of C++, “all C programs are also C++ programs, but not all C++ programs are C programs” then why don’t we learn C in a process of learning C++ ? or why don’t we learn both C and C++ in parallel ? so that we can achieve (one short, two birds) the below:

  • Save some time.
  • Easily understand the Procedural and Object-Oriented Programming.
  • Understanding the dividing line between C and C++ and much more.

This is what exactly what we try to achieve here, let us learn both C and C++ simultaneously.

We know we all don’t have too much time so, we try to keep the content of each topic short, simple and precise.

C was developed by Dennis Ricthie on a DEC PDP-11 machine, which was running on UNIX Operating System.

Now, there can be a question pop up in your mind, “I heard UNIX was written in C, how come C was developed on UNIX ?” answer is “Yes, you are correct” but the trick is “Unix was first written in Assembly Language, later it was re-written in C”.

C++ was developed by Bjarne Stroustrup, C++ is an extended version of C, initially C++ was named as “C with Classes” later renamed to “C++”.

When C is already out there and it is doing good then why do we need C++ ? By the time C++ was invented, most of the projects written in C (Procedural Programming) were reached to a point where maintaining them any longer is difficult due to the complexity of the projects like more no. of files, etc., the programming world was in need of a new approach which paved the paths for C++ (Object Oriented Programming).

History:

  • Development of C was started in early 1970’s.
  • Development of C++ was started in late 1979.

Standardization:

  • First ANSI/ISO standard of C was in 1989, which is called as “C89”.
  • First ANSI/ISO standard of C++ was in 1998, which is called as “C++98”.
  • For more information on standardization click on C, C++.

Level of Language:

  • Both C and C++ are “Middle-level” programming languages because of the following reasons:
    • Can able to manipulate “bit” (lowest level of memory).
    • Can access memory using addresses (Pointers).
    • Supports Data Types, but not strongly typed.
    • Structured, but not Block Structured.

Do you remember the first time you ever started to talk, when you are a kid ?

When we are kids and just started to talk, we can’t make bigger sentences all at once, we start small with little “words” before we grew up to make longer sentences.

Same goes with learning any computer programming language,

The architects of the programming language will reserve a set of words and assign those words with a special meaning in the language while creating it.

These words are called as “Keywords” (sometimes also as “reserved words”).

Let’s have a look at these before we start learning the language.

we don’t need to try to remember all these keywords at this moment, we will go through them one by one as we progress.

C programming language has 32 keywords in it:

auto
double
int
struct
break
else
long
switch
case
enum
register
typedef
char
extern
return
union
const
float
short
unsigned
continue
for
signed
void
default
goto
sizeof
volatile
do
if
static
while

C++ programming has another  31 keywords in it, in addition to the 32 keywords from acquired from C, so in total its 63 keywords !.

Below the table containing additional 31 keywords of C++:

asm
bool
catch
class
const_cast
delete
dynamic_cast
explicit
export
false
friend
inline
mutable
namespace
new
operator
private
protected
public
reinterpret_cast
static_cast
template
this
throw
true
try
typeid
typename
using
virtual
wchat_t

Points to remember:

  1. Keywords are case sensitive, meaning ‘auto‘ is keyword where ‘Auto‘ is not a keyword.
  2. Keywords cannot be used as names of variables, functions, classes or any user defined names.
  3. Compilers (like gcc, g++, turbo C, clang etc.,) can add additional Keywords specific to the compiler.

C Program

#include <stdio.h>
int main()
{
    printf("Hello, World\n");
    return 0;
}

C++ Program

#include <iostream>
using namespace std;
int main()
{
	cout << "Hello, World" << endl;
	
	return 0;
}

Both programs looks pretty much similar isn’t it ? but, there are some differences to note and understand.

Similarities:

  • #include : This is a Preprocessor directive, instructs the C/C++ compiler to “include some other file/code into current file/code, usually used to include header files” (stdio.h for C and iostream for C++ in this example).
  • int main () :
  • { and }
  • return 0;

Differences:

  • stdio.h
  • iostream
  • using namespace std;
  • printf() and \n
  • cout and endl

Both C and C++ are compiled languages – which means the source code (program) written in C/C++ needs to be “compiled” before it can be executed (run).

C/C++ programs can be compiled to create either of the following forms:

  1. Executable (usually called “binary file”)
  2. Shared library
  3. Static library

what is compilation ? – compilation is a process of translating the human readable, understandable instructions (programs) into machine (i.e., computer) readable, understandable and executable instructions.

what are the steps involved in compilation ? – compilation of a C/C++ involves the following steps:

  1. Preprocessing
  2. Compiling
  3. Assembly
  4. Linking

Example Program:

#include 
#define TEXT "Hello, World!"
int main()
{
        /* printing */
        printf(TEXT);
}

On a high-level, command used to complete all the compilation process in one shot (to form an executable), this is what mostly used, rest of the process is taken care by “compiler” itself.

command: gcc hello.c -o hello

Preprocessing:

  • Comments will be removed.
  • “#include <filename>” statements gets replaced with actual contents of the particular file.
  • macros gets replaced with its actual value.

command: gcc -E hello.c -o hello.i

...
extern int pclose (FILE *__stream);
...
# 864 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 879 "/usr/include/stdio.h" 3 4
# 2 "hello.c" 2
...
# 5 "hello.c"
int main()
{
 printf("Hello, World!");
}

Compiling:

  • Compiler translates the “preprocessed” source code to “assembly” code (written in assembly language).

command: gcc -S hello.c -o hello.s

        .file   "hello.c"
        .text
        .section        .rodata
.LC0:
        .string "Hello, World!"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 8.3.1 20191121 (Red Hat 8.3.1-5)"
        .section        .note.GNU-stack,"",@progbits

Assembly:

  • Assembler translates the “assembly” code into “object” code.

command: gcc -c hello.c -o hello.o

...
^@^N^@^@^@^P^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@hello.c^@main^@printf^@^@^@^@^E^@^@^@^@^@^@^@
^@^@^@^E^@^@^@^@^@^@^@^@^@^@^@^O^@^@^@^@^@^@^@^B^@^@^@
^@^@^@üÿÿÿÿÿÿÿ ^@^@^@^@^@^@^@^B^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@.symtab^@.strtab^@.shstrtab^@.rela.text^@.data^@.bss^@.rodata^@.comment^@.note.GNU-stack^@.rela.eh_frame^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^A^@^@^@^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@^@^@^Z^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^[^@^@^@^D^@^@^@@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ð^A^@^@^@^@^@^@0^@^@^@^@^@^@^@
...

Linking:

  • Compiler links the “object” code with the standard libraries and/or user defined libraries for the functions that are used in the program (“printf()” in the example)

command: gcc hello.c

Final output is an execute (a.out) file.

Data Type:

  • Defines the type of data that the associated variable can store.
  • Defines the type of operations that can be performed on the associated variable (or on actual data).
  • Defines the size of memory to be allocated by the compiler.

Properties of Data Types:

  • Size: Memory – i.e., no. of bytes required by the data type.
  • Range: no. of bits (in the allocated memory) that can be set to ‘1’ (TRUE).

C Data Types:

  1. void – not used to declare variable, it used for function return types and type casting.
  2. char
  3. int
  4. float
  5. double

Example Program:

The below program covers all the C subset data types and outputs the size of each data type on my machine.

#include 

void main()
{
    char c;
    int i;
    float f;
    double d;

    printf("size of char    : %lu \n", sizeof(c));
    printf("size of int     : %lu \n", sizeof(i));
    printf("size of float   : %lu \n", sizeof(f));
    printf("size of double  : %lu \n", sizeof(d));
}

Output:

size of char : 1
size of int : 4
size of float : 4
size of double : 8

C++ Data Types:

In addition to the data types available in C subset, below are two more data types added by C++.

  1. bool
  2. wchar_t

Example Program:

The below program covers all the C++ subset data types and outputs the size of each data type on my machine.

#include 

using namespace std;

int main()
{
    bool b;
    wchar_t wc;

    cout << "size of bool   : " << sizeof(b) << endl;
    cout << "size of wchar   : " << sizeof(wc) << endl;

    return 0;
}

Output:

size of bool   : 1
size of wchar   : 4

Modifying data types means:

  • Increasing or decreasing the default range of the data type, basically requesting compiler to allocate more or less memory than the default memory of the data type.
  • what to do with the left most significant bit – use to store positive or negative sign ? or use to store the value itself ?

What to use when:

  • Required to store lesser number than integer (but, some compilers use same size of memory for both “short” and “int”) ? Use “short”.
  • Required to store a normal integer value ? Use “int”.
  • Required to store larger number than integer / double ? Use “long”.
  • Required to store much larger number than integer or long integer ? Use “long long”.
  • Required to store a number or with a positive or negative sign ? Use “signed”.
  • Required to store a character only with in a range of ASCII (0 to 127) ? Use “signed”.
  • Required to store a number without any sign (left most significant bit will also be used to store value, so the range will be more and can accommodate larger value than “signed”) ? Use “unsigned”.
  • Required to store a character with in an extended range of ASCII (0 to 255) ? Use “unsigned”.

  • signed: applicable for character and integer data types
  • unsigned: applicable for character and integer data types
  • short: applicable for integer
  • long: applicable for integer and double

What is are variables in C/C++ ?

A variable is a name given to a particular "memory location" in computer’s memory.

Can you explain a bit more ?

Alright, for example:

int main()
{
    int a = 52;
}

In the above program, statement at line# 3 is a request to the computer asking “to allocate some space in its memory and store value 52 (compiler will do this translation).

Just like we humans have postal addresses to our house, office and other locations, each memory location (byte) in computer will also has its own unique address.

But it memory addresses looks different to our postal addresses, 0x16ba4b7ac this is how a memory address looks like (a hexadecimal value).

Ok, but why do we need variables ?

Just imagine, memory addresses like above are not given a name and if programmers need to perform any operations (like add, subtract, etc.,) on value 52, it will be difficult to do everything just by using the address right ?

so, variables are required to access values and their memory locations with ease.

Why a variable is called variable ?

Because:

  • The value stored in the variable 'a' can be changed.
  • Each the program is executed variable 'a' can get entirely a different address.

Since these factories varies, it is called a ‘variable’.

Rules to create a variable:

  • Should start either with an _ (underscore) or with an alphabets (e.g: _var, var123).
  • Case sensitive (e.g: var and Var are different).
  • Cannot be same as C/C++ keywords (e.g: int, switch etc., cannot be used).

Limitations on length of a variable name:

  • In C – maximum of 32 characters long.
  • In C++ – maximum of 1024 characters long.

const: It is a promise by the programmer to the compiler, saying that “I won’t change the value of this variable, after I initialize it”

If the promise is break then, the compiler won’t compile the program.

The below code will compile and works, even though it is changing the value of *ptr, because there is NOconst“:

#include <iostream>

using namespace std;

int main()
{
    int *ptr;
    int i = 50;

    ptr = &i;

    cout << "Value at ptr : " << *ptr << endl;

    *ptr = 100;

    cout << "Value at ptr : " << *ptr << endl;

    return 0;
}

The below code doesn’t compile, because *ptr is declared as a const” and trying to change it after initialization:

#include <iostream>

using namespace std;

int main()
{
    const int *ptr;
    int i = 50;

    ptr = &i;

    cout << "Value at ptr : " << *ptr << endl;

    *ptr = 100;

    cout << "Value at ptr : " << *ptr << endl;

    return 0;
}

Compiler will throw the below compilation error:

qualifiers.cpp:14:10: error: read-only variable is not assignable
*ptr = 100;
~~~~ ^
1 error generated.

“As simple as that.”