Printf - Format Specifiers 0 comments

I have given the program and the output corresponding to it. Also I have added comments so that it will be clear.

Code
#include<stdio.h>
main()
{
// Declaration of Variables
int iNum=86;
char cChar='V';
float fNum=86.1234567890;
double dNum=86.1234567890;


// 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);


//Octal to Hex Conversion
printf("Printing Hex value of Octal Value - %x\n",010);
//Hex to Octal Conversion
printf("Printing Octal value of Hex Value - %o\n\n",0x10);


getch();
}

Output
Integer - 86
Printing Number as Character - V
Printing Number as Float - 0.000000
Printing Number as Double - 0.000000
Printing Number as Hex - 56

Character - V
Printing Character as Number - 86
Printing Character as Float - 0.000000
Printing Character as Double - 0.000000
Printing Character as Hex - 56

Float - 86.123459
Float - 86.1234588623
Printing float as integer - -1073741824
Printing float as character -
Printing float as double - 86.123459
Printing float as hex - c0000000

Double - 86.123457
Double - 86.1234567890
Printing double as integer - -1219637671
Printing double as character - Y
Printing double as float - 86.123457
Printing double as hex - b74dce59

Printing Hex Value directly - 15
Printing Hex Value of a Number - f
Printing Hex Value of a Number(capitalized) - F

Printing Octal Value directly - 15
Printing Octal Value of a number - 17

Printing Hex value of Octal Value - 8
Printing Octal value of Hex Value - 20


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.

Using printf to display output 0 comments

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 SpecifierUsed for
%dint
%uUnsigned Integer
%luUnsigned Long Integer
%luSigned Long Integer
%oOctal Number
%ffloat
%lfdouble
%cchar
%sstring
%xHex Format(a,b,c,d,e,f)
%XHex 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 sequencesUsed for
\nTakes the cursor to the first column of next line
\nTakes the cursor to the first column of same line
\bTakes the cursor to the previous column in same line
\tTakes the cursor to the next tab
\aCreates 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.

Best Coding Practises 0 comments

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.

Compilation Process 0 comments

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...

Step 1: Lexical Analysis or Linear Analysis or Scanner : All the statements in the C program are further divided into tokens.
There are 5 types of tokens
a) Identifiers eg) Variables
b) Constants eg) 3,5,10 etc
c) Operators eg) +, -, (, ) etc
d) Keywords eg) if, else etc
e) Delimitors/Separators eg) ;

Say we have the following piece of code,
Code
if(x<5)
x = x + 2;
else
x = x + 10;

Here the tokens that will be generated are
Keywords : if , else
Identifier : x
Constants : 2, 10
Operators : +,=

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.

More about using Variables and Datatypes 0 comments

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 1
1 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).
 
Template designed using TrixTG