// To print the integer value printf("Integer - %d\n",iNum); // If I use %c for a integer, it will print its ASCII equivalent character printf("Printing Number as Character - %c\n",iNum); // I dont have any idea why it is displaying 0. printf("Printing Number as Float - %f\n",iNum); // I dont have any idea why it is displaying 0. printf("Printing Number as Double - %lf\n",iNum); // Displays hex equivalent of a number printf("Printing Number as Hex - %x\n\n",iNum);

// Displaying a Character printf("Character - %c\n",cChar); // If I use %d for a charcter, it will print its ASCII equivalent number printf("Printing Character as Number - %d\n",cChar); // I dont have any idea why it is displaying 0. printf("Printing Character as Float - %f\n",cChar); // I dont have any idea why it is displaying 0. printf("Printing Character as Double - %lf\n",cChar); // Gets the ASCII equivalent(in Hex) of character printf("Printing Character as Hex - %x\n\n",cChar);

// Displaying Float Variable - Precision is only 6 digits printf("Float - %f\n",fNum); // To explain the precision I am going to print 10 digits after decimal printf("Float - %.10f\n",fNum); // Displaying Float as a integer printf("Printing float as integer - %d\n",fNum); // Check the explanation for Displaying Double as Character printf("Printing float as character - %c\n",fNum); // Displaying Float as a Double. printf("Printing float as double - %lf\n",fNum); // Displays hex equivalent of a float - May be I have to understand how // floats are stored internally. printf("Printing float as hex - %x\n\n",fNum);

// Using double Variable printf("Double - %lf\n",dNum); // To explain the precision I am going to print 10 digits after decimal // Compare this precision with corresponding printf statement given in float. printf("Double - %.10f\n",dNum); // May be due to how double is stored internally, Check the Hex equivalent // of double below. printf("Printing double as integer - %d\n",dNum); // Displays 'Y' because it is the ASCII equivalent of HEX Value 59 // since 59 is the LSB, and Char takes only 1 byte as I have explained // in the previous posts. Same explanation applies for displaying Float as Char printf("Printing double as character - %c\n",dNum); // Printing a double value as float. printf("Printing double as float - %f\n",dNum); // Double in Hex format printf("Printing double as hex - %x\n\n",dNum);

// Printing a hex value. If we put 0x before a number, compiler treats it as // a hex number. printf("Printing Hex Value directly - %x\n",0x15); // Printing a hex equivalent of a decimal number printf("Printing Hex Value of a Number - %x\n",15); // Hex value with capitalized characters A,B,C,D,E,F printf("Printing Hex Value of a Number(capitalized) - %X\n\n",15);

// Printing a Octal Value - If we put 0 before a number, compiler treats it as // a Octal number printf("Printing Octal Value directly - %o\n",015); // Printing a octal equivalent of a decimal number printf("Printing Octal Value of a number - %o\n\n",15);

All questions that comes with why it is displaying like this for printf statements that are related to float, can be better understood if we know how float is stored internally. I will try to see how float how works exactly and then will try to make a post on this.

Also I did not get the difference between %f, and %lf when I try to print float and double values. I will be happy to hear from someone what is the difference between the two.

Let us continue from here. I have used printf statement to display the output. From the statement and the output I have given in that post, you would have guessed what should have happened. Still I will explain what is happening.

Code

printf("Sum of %d and %d is %d\n",iNum1,iNum2,iSum);

Output

Sum of 23 and 33 is 56

If you see the printf I have used in the Basic C program, it has only one argument(parameters passed to a function) - the string "Welcome to http://c-thebasics.blogspot.com". But here the number of arguments is 4. Thus the number of arguments can vary. Also the first argument should always be a string.

If you could see the code and the output, the first %d is replaced by iNum1, and second %d by iNum2, and third %d by iSum. But what is this %d ? This is the format specifier that can used in the string. The format specifier used should be based on the data type of the variable or how it should be interpretted. Since iNum1 is of integer type, we use %d. Similarly for other data types we have other format specifiers as given in the following table.

Format Specifier

Used for

%d

int

%u

Unsigned Integer

%lu

Unsigned Long Integer

%lu

Signed Long Integer

%o

Octal Number

%f

float

%lf

double

%c

char

%s

string

%x

Hex Format(a,b,c,d,e,f)

%X

Hex Format(A,B,C,D,E,F)

%%

To print %

Apart from the above, there are something called escape sequences which is used for doing special things. Following is some of the escape characters that can be used in strings.

Escape sequences

Used for

\n

Takes the cursor to the first column of next line

\n

Takes the cursor to the first column of same line

\b

Takes the cursor to the previous column in same line

\t

Takes the cursor to the next tab

\a

Creates a beep sound

\\

to print \

\'

to print '

\"

to print "

These are not the only format specifiers and escape sequences. There are many others, we will look into them later if needed.

Next most basic thing that one should know before getting into Programming is, some best Coding Practises. These practises are recommended to be followed for writing error free and efficient programs.

1) Commenting : Whenever you write a program logic, make sure you comment about the logic. This helps you understand underlying codes and the logic in it, when you revisit the code at a later time.

2) Variable Names : It is recommended to give a variable name, which is meaningful. One common mistake programmers do is, giving variable name as i,j,k etc for array indexers.

3) Indentation : Make sure you properly indent blocks of codes, so that it is easily readable. When there are lots of opening and closing braces your code will become unmanageable if you didnot indent. You wont be able to see where a block of code starts and ends.

4) User Inputs : Make sure that program logic will be able to handle all possible user inputs. Many times, we wont see what will be the possible inputs from the users. For eg) assume that we wrote a program to find whether a number is prime or not. Most times, we wont check for the integrity of the user inputs. If we give negative numbers, then also it will show whether the number is prime or not. Sometimes our code will say 1 as prime number, if we did not make necessary checking for the user input as 1. Take another example of finding average of 5 marks which is given by user. Most times we assume that user will give something between 0 and 100. But what if the user gives a negative number or something above 100. The program should ignore such cases/throw errors.

5) Overflow/Truncation: When the result of addition or mulitplication increases beyond the actual value a datatype can hold, error occurs. And instead of floating point operation as in finding average, normal integer operation is performed error will occur in the result. So checking the data type of variables used is very important and we should make sure that user inputs corresponds to the variable of the data type

6) Memory : Use variables of appropriate data types so that we use memory for what we need and we wont be wasting memory. It is not a good practise to use long int, when you are sure that values stored in the variables will be in the range which int variable can hold. Usage of arrays with very large maximum index will create wastage of memory. Decide on the maximum index, which you thing you will need. There is other options like Linked List also.

7) Code Optimization : Make sure you follow code tuning techniques, so that your code will use less memory and takes less times to execute. Loops should be properly handled, and exit conditions should be available in the loops so that it wont get into infinite loop.

8) Error Handling : The Program should have appropriate error handling techniques and the user should be displayed with messages which the user can understand. Logging can be done for debugging incase of any errors, so that we will be easily trace the problem and fix them.

Incase if you find any improvements that can be done in the code snippets that you find in this blog, let me know so that others will be benefited.

Everytime I say compilation and execution. What is exactly happening when I say compilation and execution. We write a program in Dev CPP, save it and then compile it. What internally happens is some series of steps that will create an executable file which can be understood by the operating system so that we can run/execute it.

The program we write is according to the standards/syntax that is specified for C. Only then the C Compilers can understand our programs. These standards are specified keeping in mind, how easy the developers can understand the programs. But the computer system can understand only 0s and 1s (which will be difficult for the developers to deal with). It doesnt know what is "printf" and what is "scanf" unless it is converted to someother form the computer can understand. This translation of our source program to machine understandable object codes is done by compilers. But will it blindly convert whatever we write ? definitely not. So lets look into what are all the steps that are taking place...

Here the tokens that will be generated are Keywords : if , elseIdentifier : xConstants : 2, 10Operators : +,=

Step 2: Syntax Analysis : It checks for syntax of our statements. It will then generate a parse tree for our statements. Something like the following (eg. x=2+5)

= / \x + / \ 2 5

In case of any errors in the syntax like x=x+; It misses one identifier/constant after '+' operator. So it will generate an error.

Step 3: Semantic Analysis : Checks for type mismatch. Say we have declared variable x as float. And we are trying to use Modulo operator (% - finds the reminder in division operation) on x. The type of x is float, and we cant use % on that variable. So this causes an semantic error.

Now when the same program is used in different platforms/machines and compiled, the above phases are the same. The above operations output only changes when the Source Language is changed. So since the above phases are largely dependent on the source language, they are called front-end operations.

Step 4: Intermediate Code Generation : The actual machine understandable code is generated after phases like Code-Optimization(step 5) and Code Generation(step 6). Since they are largely dependent on the Target Machine, they are called Back-End Operations. And these phases are independent on the Source Program used.

In order to make compilation process more efficient, so that we need to have less number of backend and front end operations for compiling from programs in many source languages for many platforms, we need to introduce this step of Intermediate Code Generation. This creates a logical separation between the machine dependent phases and source dependent phases.

Step 5: Code Optimization: Inorder to make the execution of programs efficient, like usage of less resources and time efficient, compiler will optimize our code upto some extent. We should also remember that we should write the codes by following some code tuning techniques (will be explained later).

Step 6: Code Generation: Final step is the actual generation of code for the target machine. It is dependent on the architecture of the CPU and other devices.

In all the steps, compiler will make use of Hash Tables to keep track of name,type, address,size of variables. It will also make use of Error Processing module for reporting and recovery of errors that occurs in each stage of compilation. Error Reporting helps in getting the line in which error has occured and possible reason. Error Recovery will try to correct or skip lines where error has occurred and will allow the compiler proceed with compilation for the rest of the lines.

Thats the basics about compilation process. Now the generated output code can be executed to give the actual output of the program.

Let us continue from my previous post. I said I have a question. Lets look into it.

Memory location is mapped to variable name. But will it map all memory of all 4 bytes to Variable Name. Answer is, it actually maps only the memory location of lower most byte. By the way, Lower most byte is the least significant byte.

Say I have 1023 (binary equivalent - 00000011 11111111). We assume that Most Significant Byte(00000011) is stored in memory location 2001 and 11111111 is stored in memory location 2000. Then variable name will be mapped to memory location 2000.

And why does it map to 2000. Why not 2001 ?

Before coming to the answer we should know some basic terms. 1 bit - 0 or 11 byte - 8 bits

Every system has some basic memory storage called WORD. A word is grouping of bytes (It may be 2,4 etc. and it depends on the system.) What the system does is, it gives memory address to each WORD. Assume a system uses 4 bytes for a word, and I write a a C program, where I declare a character variable (which takes 1 byte) and declare 2 more integer variable (which takes 4 bytes). Usually when the program is very small with only 2 variables, during execution those variables are stored in continous memory locations. So I will have a look at the address mapped to the variable. What i see is that memory address 2000 is assigned for character variable and memory addresss 2004 and 2008 is assigned for the two integer variables. So even though the character variables takes only 1 bytes, actually the memory used up is 4 bytes (I dont know why, may be due to the basic memory storage concept).

Note : I will come up with the program used for this purpose later while explaining memory allocated for data types.

So memory locations 2000, 2001, 2002, 2003 where in use. But actually when we store something in the character variable, it gets stored in 2000. Hence Instead of mapping 2003 to the character variable, 2000 is mapped to the character varaible. Also while making basic operations like addition, we usually start from the Least significant digit. So it will be easy if the program fetches the LSB first and then proceed to the MSB. Inorder to avoid the overload in finding the LSB, memory location of LSB is mapped to the variable.

We will better understand this concepts while we come across UNIONS (a secondary data type).

// Display Output printf("Sum of %d and %d is %d\n",iNum1,iNum2,iSum);

/* Changing inputs */ iNum1 = 10; iNum2 = 23;

/* Process Again */ iSum = iNum1 + iNum2;

// Display Output Again printf("Sum of %d and %d is %d",iNum1,iNum2,iSum);

getch();}

The above program introduces many new things to you. First thing is Comments. To make the program look more understandable, we can use comments to describe certain blocks of code. So we use comments. Comment Lines are ignored by compiler while compiling. There are two types of comments - Single line comment and Multiline comment. Single Line comment can be made by starting the line with // and multiline comment can be made by starting the comment with /* and ending the comment with */

Next thing that is introduced here is variables and data types. Recall the third paragraph in this Post. We can store data/values in memories and can give those memory locations as input to the add function. So if we need to change the value for which we need to find sum, we simply change the value in those memory location and call the sum function with the same address location.

But as explained earlier, C program makes things easy for us. We don't need to specify where to store our data. It simply finds a free memory location and puts our value in it. So how do we know where our value is stored ? How can we change the value in that memory location ? That is where Variables comes into picture. We just name the memory location (whatever it might be). We use that variable name to identify the memory location. Internally C will map the variables names to the memory location using a Table maintained by it.

Thus when we DECLARE a variable(int iSum;), a new memory location is allocated and the address is mapped to the variable name iSum. So even without knowing the memory location, we would be able to change the values in that memory location. Hence the name "Variables". Now when we INITIALIZE a variable(int iNum1=23;), inaddition to declaration, the program also stores the value 33 in the memory allocated.

Now I know you will have a question. What will be present in the Variable which is not initialized? At any point of time, a memory location will have random combination of 0s and 1s or some value which was previously stored during execution of someother program. So it will contain some random number which we can't guess. We call those values GARBAGE VALUES.

Ok I have said it will allocate memory for the variable. But how many bytes of memory will it allocate ? Now comes datatype into picture. As explained here, Int means integer and the memory size for it is 4 bytes (depending on the compiler/system). So when we specify "int a", 4 bytes of memory is allocated. (Now I have a question again, have a look at the next post for what it is)

Now the statement for processing the input(iSum = iNum1 + iNum2;), It is something like 2E [2000] [2004] (as explained here). Instead of giving the memory address [2000],[2004] we specify the variable names. Instead of specifying 2E, we specify the operator +. Now we can also specify where to store the result through iSum =

For the reasons stated here, there should be some data type range that every system should have. Depending on the sytem/compiler you are working on, these range of data types can vary. So don't worry if you see different results in your computer (I will give and explain a program later to see what is the range of data type that your computer can store).

Data Type

Size

Range

int

4 bytes

–2,147,483,648 to 2,147,483,647

char

1 byte

–128 to 127

float

4 bytes

3.4 e-38 to 3.4 e+38 (7 digits precision)

double

4 bytes

1.7e-308 to 1.7e+308 (15 digits precision)

There are variations of primitive data types such as signed and unsigned char, signed and unsigned int, short and long int, signed and unsigned long int, Note : 1 byte = 8 bits

Digital Computers store datas in zeroes and ones. Any data we want to represent are converted to binary equivalent (zeroes and ones) and stored in the memory. Let us say we have 33, the binary equivalent of 33 is 100001. 33 will be actually stored as 100001 internally. Similarly if we have a character 'A', the ASCII equivalent of that character is taken and it is then converted to the binary equivalent and stored.

But had a look at the variations in the number of digits in the binary equivalent ? 33 takes 6 characters (100001), but 23 takes 5 (10111), similarly the number of bits (binary digits) differ for each number. So to create uniformity and to make the system understand where a number/character starts and end, they have introduced something called padding of zeroes. We will have fixed number of bits, say 8. So every number will be stored as 8 bit binary number. That is 33 will be stored as 00100001 and 23 will be stored as 00010111. This makes the compiler easy to understand where it should start reading a number.

Ok, What can we do for storing characters whose ASCII equivalent is also a number and is stored as binary the same way as a number. Wont there be a contracdiction whether it is a character or number? How can we differentiate it is a number or a character ? This is the reason we have data types. We tell the compiler whatever stored in this memory location is a charcter, and whatever we store here is a number through data types.

Ok, But 8 bits can store only from 0 to 255 (from 00000000 to 11111111). What can we do for higher numbers? Ok we can increase the number of bits from 8 to 16 or 32 or 64 etc. But the problem of extending the number of bits required to store one number is, we have to append more and more zeroes thus wasting the memory. This is one of the reasons why we have variations in Primary Data types. Also we need to have something called, range of values each data types can store. If we use the correct data types, we can save memory.

Next post will explain the range of values that can be used by a data type.

When we are reading something, we know that it is a alphabet, it is a number, it is a decimal number etc. For the compiler to know what type of data we are dealing with, we must specify the data type. Following are the primary data types that can be used in C.

Example

Data Type Name

Data Type

123, -23

Integers

int

12.5, 3.4E-38

Floating Point

float

a

Characters

char

1.7E-308

Double Precision Float

double

When I say primary, there are some secondary/derived data types also. We will look into those data types later. Also there are some variations of primary data types. To know more about, those data types, we need to know what is actually happening internally. My next post will explain how computers store data.

Enough of basics, we will quickly move into programming. I will start with a very simple program and start explaining to you on how to write a C Program and compile it using Dev CPP. Whatever may be the compiler, the steps will be almost similar. Have a look at the following program. It simply displays "Welcome to http://c-thebasics.blogspot.com".

As I have already described in this post, there are many inbuilt functions and they are grouped to form library files. These files can be included in the program and the functions in those library can be used. The first statement includes the standard input/output library. Extension of the file .h stands for Header file, it contains the definition (let us see what they are later) for input/output functions. This is called a Pre-processor directive (Processed before compilation phase)

main() - Is a user defined function. Every program starts execution from this point. The opening brace { and closing brace } tells the compiler where the function starts and ends.

printf - As I have said, it is a inbuilt function. Its job is to display whatever is given as input to it. Here the input is a string (group of characters).

Now what to do with this piece of code ? Open your C compiler, and open a new source file in it. Type the above code and save it as Welcome.c , where .c is the file extension.

If you are using Dev C++, go to Build -> Compile & Run (F9).If you are using TurboC, go to Run -> Run (Ctrl + F9)

Ok, but what happened ? Nothing seemed to come up? Yes, because the output window has already came and closed in Dev C++. In TurboC, Press Alt+F5, to get to the outscreen.

In DevC++, the window has already closed. So we need a little work around to see the output.

So what have we added extra ? getch(); What it does ? It is again a inbuilt function, and it is used for accepting a Single Character from our Keyboard, so until we press any key, the cursor stays there, Hence we will see the output. So usually I used to put this getch(); as the last line in a program.

Did you note something ? we have a semi colon at the end of every statement. This is how we tell the compiler that its an end of a line/statement.

Another point to be noted here is that, the above program still runs fine in Dev C++, without errors even if the stdio.h header file is not included. Possible reason is that, it is automatically included by DevC++ compiler when compiling & executing the program. In TurboC, it will show error.

You should have an operating system installed in your machine :d. And you will require one C Programming complier like Turbo C, Borland C etc for your operating system. Just google for the names you will find the place to download them. Install that compiler into your system.

I use Dev CPP. It is a C++ compiler, but it can compile C source also. I prefer using that because I feel it is easy for me to edit and compile the programs. Syntax highlighting also helps me a lot. Also if there is any run time errors, or infinite loops it will be easy for me to quit the program, without damaging the source code files that are open.

Let us think of a scenario. I need to find answer for 2 to the power 5. My algorithm will be something like this. I place 5 in a memory location 1. Place 2 in a memory location 2. Multiply value in memory location 2 with 2, and everytime I multiply, I will decrement the value in memory location 1 until it reaches 0. We don't need to specify where we need to store the values. Those jobs are taken care by the compiler. It reads the programs, separates them into smaller parts called tokens and checks them against predefined syntax. It then converts the program into codes that machines can understand. More like a conversion from Human readable form to Machine Readable form.

Now, since we will be requiring to find Power of certain numbers many times in a program, we can puts these program into a block called functions. In order to find the power, we just need to call these functions and pass our arguments/inputs (say 2 and 5). Similar to this power function, there will be many other function that are predefined when we install compilers like Turbo C, Borland C etc. These are standards that are set and every compiler for C Programming will follow those standards.

In order to make it more organised, those Predefined functions called INBUILT functions are grouped and put into a package called library files. So all math related functions will be put into one package. All string related functions will be put under one package etc. When we need to make use of these inbuilt functions, we simply include those files into our program.

Before one should learn something, they must know what they are learning. Let us say, we have a Computer. In the simplest form a computer consists of a Input device (like our keyboard), a Output device (like our monitor), a CPU (for processing the input we give), a memory device (like RAM, Hard Disk etc for storing the programs and datas we supply).

Now, how does computer function with all these ? Computer doesn't have intelligence. It simply does what we ask it do through Programs. Every CPU has it own set of operations that it can perform like Addition, Subtraction, Multiplication, Division, comparision etc. We can make use of these operations to occamplish complicated tasks, Say finding the n'th power of a number. For that we need to specify a series of instructions (Program) to the CPU. The data is present here, and the program is present here. The CPU then starts executing the program and sends the output to the output device as we have requested.

Earlier days, we used to write Machine Codes. Machine codes are codes which corresponds to each basic CPU operation. Say we have a code 2E for Addition. (2E - Hexadecimal number - Just an example). So to add two numbers we need to send something like 2E 34 23 to the CPU. Now the CPU understands that it needs to perform addition operation on 34 and 23. As the requirement for dynamic data increased, we place the data in the memory location and send the instruction like 2E [2000] [2004]. Now the CPU knows that It needs to take data from memory locations (address given to memory) 2000 and 2004 and add them.

As it was very difficult for us to remember each and every instruction code, we started developing something call Mnemonics. Where we simply say Add 34,23 and there will be a compiler which will understand Add 34,23 and sends the ouput as 2E,34,23 to the CPU. CPU then processes this. This compiler itself is a program written with the instruction codes. Still mnemonics are very hard, because we still need to specify the address where the data should be stored and where the CPU needs to put the output. Also it is not easy to handle loops, control statements etc without actually knowing the instruction sets of CPU.

The result of all our expectations for faster and efficient programming is C Programming Language. C is a general-purpose computer programming language developed in 1972 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system. Though there are many languages that were developed prior to C, it is one of the basic languages for understanding many other Programming langugages. Knowing C, we can learn other programming languages very easily.

I am quite sure that if you understand how C Programming works, you will enjoy programming.

This blog is all about Basics in C Programming. Though there are lots of newer, advanced and much efficient languages developed these days, I believe that Language C is one of the root which one should know to easily understand other programming languages. Similar to HTML, which is very much required for web designing, I believe that one should know C. So I am going to explain to you what I have understood from my graduation and other programming expertise. The contents posted here are from my understandings, and if you see any contradiction from what you have learnt, I will be glad to learn from you. Suggestions, Comments, Feedbacks are all welcome. You can drop a mail to talktotrix[at]ymail[dot]com or can comment here.

SUPPORT US

The contents posted here are from my understandings, and if you see any contradiction from what you have learnt, I will be glad to learn from you. Suggestions, Comments, Feedbacks are all welcomed. You can drop a mail to talktotrix[at]ymail[dot]com or can comment here in appropriate posts.