Thursday, July 8, 2010

Understanding Filesystems Part-1

For the past few days, I am trying to understand the memory fundamentals behind the Filesystems. I will not say it a complete description of filesystems, but my worth notable observations on my current filesystem.
Experimental Setup:
Hardware:
1. A PC running both Windows and Linux [Fedora13].
2. An Experimental Pendrive. Please dont have any valuable information in it. We are going to format it.
3. Another pendrive to transfer data between Linux and Windows. I did not find a safe and better way to do this, since I am still a newbie to linux.
Software Tools:
1. HexEdit [http://www.physics.ohio-state.edu/~prewett/hexedit/]. A tool to display the raw data.
2. dd Utility for Windows [http://www.chrysocome.net/download]. Utility to take image of source to destination. I use to call it a "PHOTOGRAPH TOOL" ;).

Though Windows is a sophisticated operating system, it hides all the micro level details from the users. So user may not be aware of what exactly is happening inside the Computer box. So take an Operating System like linux, that will open up things if demanded by the user.
Now lets start our experiment.
Let us understand how my computer interprets a pendrive memory.
I booted into Linux. Pendrive got automounted. Following are commands to be executed and their responses.

[root@localhost ~]# cat /proc/partitions
major minor #blocks name

8 0 20971520 sda
8 1 19921920 sda1
8 2 1048576 sda2
8 16 7831552 sdb
8 17 7825423 sdb1
8 32 976762584 sdc
8 33 976762552 sdc1

In the above response, /dev/sdb is Experimental Pendrive and /dev/sdc is Data Transfer Pendrive.
Now issue the following command in the terminal.

[root@localhost ~]# fdisk /dev/sdb

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
switch off the mode (command 'c') and change display units to
sectors (command 'u').

Command (m for help): p

Disk /dev/sdb: 8019 MB, 8019509248 bytes
247 heads, 62 sectors/track, 1022 cylinders
Units = cylinders of 15314 * 512 = 7840768 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xc3072e18

Device Boot Start End Blocks Id System
/dev/sdb1 1 1022 7825423 83 Linux

Command (m for help): q


In this post, I am going to dissect the above response that I got from my linux machine.
When I give a fdisk /dev/sdb, it entered a command response mode.
I gave the command 'p'. It returned me the partition details in CHS [Cylinder Head Sector] format [which is conventional in case of harddisks]. Lets take some observations.

Disk /dev/sdb: 8019 MB, 8019509248 bytes
247 heads, 62 sectors/track, 1022 cylinders
Units = cylinders of 15314 * 512 = 7840768 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xc3072e18

Observation-1: Disk is detected as /dev/sdb.
Observation-2: Size of disk is 8019MB = 8019*1024*1024 Bytes = 8019509248 bytes. Yes its an 8GB Pendrive.
Observation-3: How is it interpreted in the system? What is this "247 heads, 62 sectors/track, 1022 cylinders"?
Head: Data is written to read from a device called "Platter". A Platter comprises of two heads one on each side.
Track: The track is a thin concentric circular strip on a Platter surface which actually contain the magnetic regions of data written to a disk drive.
Cylinders: A set of tracks with same track no (ie. on the same platter surface) are called Cylinders.
Sector : A track is divided into 512 byte segment called Sectors.

Now lets do the calculation.
247 heads, 62 sectors/track, 1022 cylinders

means there are 247 heads to read the tracks.
There are 62 sectors per track. Seems like only one track per cylinder.
There are 1022 such cylinders are available in my pendrive.

Total Size of Pendrive (in Bytes) = No. of Heads * No of Sectors/track * No. of Cylinders * 512 Bytes.
Total Size of Pendrive (in Bytes) = 247 * 62 * 1022 * 512 Bytes
Total Size of Pendrive (in Bytes) = 8013264896 bytes
Total Size of Pendrive (in Bytes) = 8013264896 / (1024 * 1024 *1024) Gigabytes
Total Size of Pendrive (in Bytes) = 7.4629344940185546875 Gigabytes

This is how the calculation goes.

In my next post, let us see what exactly a "formatting of Pendrive" means and use the tools above.

Wednesday, June 3, 2009

Cracking the Myths Behind the Microcontroller Clock

Hi,
I being a embedded engineer, would like to discuss something interesting with respect to a controller. Every microcontroller will have its operational frequency. This frequency is provided by a Clock Source. This can be an internal or external. Though I was working on Micro controllers for a long time, I have to admit that clocks were a big black box for me. So I decided to break all the mystery behind Clocks. This understanding is the first step to optimize your code. This is the point where hardware and firmware meet eachother. For an embedded engineer, who is doing his development in C, need to take these things into consideration.

Now that its high time to understand what a clock meant to a Microcontroller. I had a small experimental setup. This consists of my custom ATMega128L board, a tektronics oscilloscope and a multimeter. I program in AVRStudio, which uses WinAVR to compile the code and generate hex file. This ATMega128L can run at a max frequency of 8MHz and can operate at 3.3V. I used an internal RC Oscillator @8MHz.

Now lets get into some analysis.
What is this 8MHz mean? This is the speed at which our internal RC Oscillator oscillates. That is the clock oscillates 8000000 times every second, which means that it takes 125nanoseconds(=1/8000000) for one oscillation. ATMega128L being a RISC Processor, each of its instruction is executed in one clock cycle. So one instruction is executed per cycle. Fine, if this is going to be the case, then how fast can I toggle a General Purpose Input Output Pin (GPIO Pin)? This is the place where our coding style comes into picture. In the later part of the article, I am going to explain how Coding Style affects the speed. At the end of this article you will understand how the clock affects the speed.


//Example-1:
#include "avr/io.h" //Controller Specific Header File.
//Start of Main - Entry into the program.
int main()
{
DDRD = 0x01; //Direction of the PORTD0 Pin is set as Output.
while(1)
{
PORTD |= 0x01; //Make PortD0 high,keeping all other pins as it is.
PORTD &= 0xFE; //Make PortD0 low,keeping all other pins as it is.
}
}

The following is the waveform that I got when I executed this code.



This program produces a square waveform, and does nothing. Guess what is the frequency of the square waveform I got. It is hardly around 1.316MHz. Are you surprised to see a 8 MHz clock to ~1.3 MHz.

This result provoked me for further experimentations. I tried to use some directives that I got with AVRlib. Following is the code that I tried.


//Example-2:
#include "avr/io.h" //Controller Specific Header File.
//Start of Main - Entry into the program.
int main()
{
DDRD = 0x01; //Direction of the PORTD0 Pin is set as Output.
while(1)
{
sbi(PORTD,0); //Make PortD0 high,keeping all other pins as it is.
cbi(PORTD,0); //Make PortD0 low,keeping all other pins as it is.
}
}

I ended up with the same result. The waveforms looked alike. Following is the waveform I got.



My next attempt was a bit logical. I used EXOR operation, thinking that each EXOR operation will be completed in one cycle. Following is the code outcome of this experiment.

//Example-3:
#include "avr/io.h" //Controller Specific Header File.
//Start of Main - Entry into the program.
int main()
{
DDRD = 0x01; //Direction of the PORTD0 Pin is set as Output.
while(1)
{
PORTD^=0x01; //Make PortD0 high,keeping all other pins as it is.
PORTD^=0x01; //Make PortD0 low,keeping all other pins as it is.
}
}


But this infact increased the clock time period. Following is the output waveform.



This time I wanted to try something simple. So I wrote a program like this. Some may think that it is foolishness. But it really worked.

//Example-4:
#include "avr/io.h" //Controller Specific Header File.
//Start of Main - Entry into the program.
int main()
{
DDRD = 0xFF; //Direction of the PORTD0 Pin is set as Output.
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
return 0;
}

I was amazed to see the waveform!!! Following is the waveform.



There are two things that I changed in the Example-4 compared to other examples. They are
1. I removed the while command.
2. I removed the logical operation on the ports.

Let us understand which instruction gulped how many instruction cycles. So I tried the following code.


//Example-5:
#include "avr/io.h" //Controller Specific Header File.
//Start of Main - Entry into the program.
int main()
{
DDRD = 0xFF; //Direction of the PORTD0 Pin is set as Output.
while(1){
PORTD = 0x01;
PORTD = 0x00;
PORTD = 0x01;
PORTD = 0x00;
}
return 0;
}


Following are the Output waveforms.





Everything looks fine. An Article needs conclusion. It took me a long time to wrap things up. Here is the conclusion and reasoning of what every Example code meant.

The controller is running at 8MHz. This means that each instruction takes 125 nanoseconds.

Example-1:
In this code, we used a while loop, one OR operation, one AND operation and two assignment operations. A while loop takes two cycles, OR, AND and Assignment operation will take one cycle each. So totally there are 6 clock cycles used (2 for while loop + 1 for OR operation + 1 for AND operation + 2 for two Assignment Operation). Time taken would be 125 nanoseconds*6 = 750 nanoseconds. We are getting approximately 770 nanoseconds. Thus justified.
Example-2:
In this code, we tried using a directive that came with AVRlib. Surprisingly the sbi(), cbi() were also been implemented in the same way as previous one. Since they are #define 's, they are being handled at the preprocessor level itself. Thus 770 nanoseconds.
Example-3:
In this code, when we see from outside, it seems to be simple logical EXOR operations. But when we see this code carefully, it is different. Each logical EXOR will take two clock cycles. So to execute each while loop in this code, the controller will take 8 Clock Cycles (2 for while loop, 2 for each EXOR. So 4 Cycles and 2 Assignment). So 125 ns * 8 = 1000ns (~1.030 microSeconds).
Example-4:
In this code, one assignment operation for making the GPIO logical one and one assignment operation for making the GPIO logical zero. So only two clock cycles are used. This leads to a maximum frequency which is 4MHz. Time taken will be 125ns*2=250ns (~256 ns). Thus justified.
Example-5:
In this code, in addition to assignment operations, a while loop is also added. So time should be for this two pulses, it should take 256ns and for while loop, it will take two clock cycles (which is 512 ns).


If you like this article and be able to appreciate this, dont forget to mail me your comments. my email id is "vbalaji[dot]acs[at]gmail[dot]com". Thanks for your patience.

Wednesday, February 4, 2009

Interesting C Program - 25

Hi all,
I am here with a really interesting c program that I have developed today. It is a text based paint program. It uses ncurses library. Here goes the program.


/*
------------TEXT BASED PAINT PROGRAM--------------
*/
#include "stdio.h"
#include "stdlib.h"
#include "curses.h"
int rmax,cmax;
int crow,ccol;
char drawchar = ' ';
void moveup(void);
void movedown(void);
void moveleft(void);
void moveright(void);
void delcurrent(void);
void bckspace(void);
void delup(void);
void toggledraw(void);
int main()
{
WINDOW *scrn;
char key;
//----------------------------------------
printf("\n-----------------------------\n");
printf("\n Welcome to TextPaint\n");
printf("\n w - move up\n");
printf("\n a - move left\n");
printf("\n s - move down\n");
printf("\n d - move right\n");
printf("\n r - remove current character\n");
printf("\n b - remove character in the left\n");
printf("\n v - remove character in the top\n");
printf("\n t - toggle between moving and drawing\n");
printf("\n-----------------------------\n");
printf("\n Press ENTER Key to Continue\n");
getchar();
scrn = initscr();
cbreak();
noecho();
getmaxyx(scrn,rmax,cmax);
clear();
refresh();
crow = 0;
ccol = 0;
//----------------------------------------
while(1)
{
key = getch();
switch(key)
{
case 'w':
moveup();
break;
case 'a':
moveleft();
break;
case 's':
movedown();
break;
case 'd':
moveright();
break;
case 'r':
delcurrent();
break;
case 'b':
bckspace();
break;
case 'v':
delup();
break;
case 't':
toggledraw();
break;
default:
endwin();
printf("!!!You Have Come out of TextPaint!!!\n");
return 0;
break;
}
}

endwin();

return 0;
}

void moveup(void)
{
crow--;
if(crow<0)
{
crow = rmax;
}
move(crow,ccol);
delch();
insch(drawchar);
refresh();
}
void movedown(void)
{
crow++;
if(crow>rmax)
crow = 0;
move(crow,ccol);
delch();
insch(drawchar);
refresh();
}
void moveleft(void)
{
ccol--;
if(ccol<0)
ccol = cmax;
move(crow,ccol);
delch();
insch(drawchar);
refresh();
}
void moveright(void)
{
ccol++;
if(ccol>cmax)
ccol = 0;
move(crow,ccol);
delch();
insch(drawchar);
refresh();
}
void delcurrent(void)
{
move(crow,ccol);
delch();
//insch(' ');
refresh();
}
void bckspace(void)
{
ccol--;
if(ccol<0)
ccol = cmax;
move(crow,ccol);
delch();
refresh();
}
void delup(void)
{
crow--;
if(crow<0)
crow = rmax;
move(crow,ccol);
delch();
refresh();
}
void toggledraw(void)
{
static int i;
i++;
if(i%2)
drawchar = '-';
else
drawchar = ' ';
}

Monday, January 19, 2009

Interesting Articles-1 Linux Filetypes

Hi Readers,
This time we will understand the File types in Linux.
Linux File Types:
Regular files:
As the name implies; used for data, executables programs, and anything else you might like. In an 'ls -l' listing, they show up with a '-' in the first character of the permission (mode) field.

Directories:
Special files for assiciating file names with inodes. In an 'ls -l' listing they show up with a 'd' in the first character of permissions field.

Symbolic links:
In an 'ls -l' listing, they show up with an 'l' in the first character of the permission field.

Devices:
Files representing both physical hardware devices and software pseudo-devices. There are two kinds:
Block Devices:
Devices on which I/O happens in chunks of some fixed physical record size such as disk drives and tape drives. Access to sch devices goes thruough the kernels buffer cache. In an 'ls -l' listing, they show up with a 'b' in the first character of the permissions field.
Character Devices:
Also known as raw devices. Originally, character devices were those on which I/O happened a few bytes at a time, such as terminals. However, the character device is also used for direct I/O to block devices such as tape drives and disk drives bypassing the buffer cache. In an 'ls -l' listing, they show up with a 'c' in the first character of the permissions field.

Named Pipes:
Also known as FIFO files. These special files acts as pipes; data written into them by one program can be read by another; no data go to or from the disk. FIFOs are created with the mkfifo command. In an 'ls -l' listing, they show up with a 'p' in the first character of the permissions field.

Sockets:
Similar in purpose to named pipes, they are managed with the socket interprocess communication (IPC) system calls. In an 'ls -l' listing, they show up with a 's' in the first character of the permissions field.

Tuesday, December 9, 2008

Interesting C Program -24

Hi all,
Here is the alpha version of the shell that I recently developed. This program runs fine in Linux. This shell will accept max 3 arguments.

Here's the program:

#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "sys/wait.h"
char InputData[100];
char Command[100];
char Parameter1[100];
char Parameter2[100];
unsigned int CommandLength = 0;
unsigned int Parameter1Length = 0;
unsigned int Parameter2Length = 0;
unsigned int i=0;

void read_command(void);

int main()
{
int status;
printf("[Balaji]>");
while(1)
{
read_command();
if(fork()!=0)
{
//waitpid(-1,&status,0);
wait(&status);
}
else
{
if((Parameter1[0] == '\0')&&(Parameter2[0]=='\0'))
{
execlp(Command,Command,'\0');
}
else if((Parameter1[0] != '\0')&&(Parameter2[0]=='\0'))
{
execlp(Command,Command,Parameter1,'\0');
}
else
{
execlp(Command,Command,Parameter1,Parameter2,'\0');
}
}
printf("[Balaji]>");
for(i=0;i<CommandLength;i++)
{
Command[i] = '\0';
}
for(i=0;i<Parameter1Length;i++)
{
Parameter1[i] = '\0';
}
for(i=0;i {
Parameter2[i] = '\0';
}
}
}
void read_command(void)
{
unsigned char ParameterStart = 0;
gets(InputData);
for(i=0;InputData[i]!='\0';i++)
{
if((InputData[i]!=' ')&&(ParameterStart==0))
{
Command[i]=InputData[i];
CommandLength = i;
}
else if((InputData[i]==' ')&&(ParameterStart ==0))
{
Command[i]='\0';
CommandLength=i;
ParameterStart = 1;
}
else if((InputData[i]!=' ')&&(ParameterStart==1))
{
Parameter1[i-CommandLength-1] = InputData[i];
Parameter1Length = i-CommandLength-1;
}
else if((InputData[i]==' ')&&(ParameterStart==1))
{
Parameter1[i-CommandLength] = '\0';
Parameter1Length = (i-CommandLength);
ParameterStart = 2;
}
else if((InputData[i]!=' ')&&(ParameterStart==2))
{
Parameter2[i-CommandLength-Parameter1Length-1] = InputData[i];
Parameter2Length = i-CommandLength-Parameter1Length-1;
}
else if((InputData[i]==' ')&&(ParameterStart==1))
{
Parameter2[i-CommandLength-Parameter1Length] = '\0';
Parameter2Length = (i-CommandLength-Parameter1Length);
ParameterStart = 3;
}

}
if((InputData[i]=='\0')&&(ParameterStart==0))
{
Parameter1[0] = '\0';
Parameter2[0] = '\0';
Parameter1Length = 1;
Parameter2Length = 1;
}
}


.
gcc -o balaji shell.c
./balaji

Saturday, December 6, 2008

Interesting C Program -23

Hi all,
Its long time since I updated my blog. This time, a real weird puzzle is here for you to solve.
Observe the following program...


#include "stdio.h"
#include "stdlib.h"
int main()
{
char data[20];
printf("Type Something Here with spaces: ");
scanf("%s",&data);
printf("%s",data);
system("pause");
return 0;
}


when I run the code, I asks us to type something with spaces.
I typed "abcd efgh".
Try to guess the output.



The output is just "abcd".

Alas what happened to "efgh"!!!

The answer is in scanf's implementation.

It has been mentioned in "http://www.opengroup.org/onlinepubs/009695399/functions/scanf.html", that,
s
Matches a sequence of bytes that are not white-space characters. The application shall ensure that the corresponding argument is a pointer to the initial byte of an array of char, signed char, or unsigned char large enough to accept the sequence and a terminating null character code, which shall be added automatically.



Isn't it weird?

Wednesday, January 16, 2008

Interesting C Program -22

Hi all,
This month's LFY had an interesting C Program that caught my attention. Lets discuss that in detail.

I have the following C Program.

#include "stdio.h"
int main()
{
struct value
{
int val:1;
};
struct value x;
x.val = 1;
printf("%d",x.val);
return 0;
}




What could be the output of the following Program?

I too thought that the output would be 1. But its not 1, but -1. Why?


The explanation goes like this.

The structure member has been declared "int", which is "signed int"

We all know that the MSB of a signed int will be the sign bit. If it is 1 then the number is negative and if it is zero the number is positive.

Right, now my question is, if the val takes the MSB ie. in binary format 1000 0000 0000 0000, which should be a -0. If the val takes LSB ie. in binary format 0000 0000 0000 0000, which should return 1. Why is it printing -1?


The explanation goes like this.

Any signed integer will be represented in its two's complement form.

Try out the following program.

#include "stdio.h"
#include "math.h"
void func(int x);
int main()
{
int x=-10;
func(x);
return 0;
}
void func(int x)
{
unsigned char x1;
signed int i;
for(i=15;i>=0;i--)
{
x1 = ((x/(unsigned int)pow(2,i))%2)+0x30;
printf("%c",x1);
}
}


This will print -10 in binary format. If you look at it, you will get "1111111111110110", which is two's complement of 10.


So the output, 1000 0000, will be printed in two's complement form, which is 1000 0001. This is signed integer. So outputs -1 instead of 1.

Thursday, December 13, 2007

Interesting C Program -21

My friend came to me with the following weird C puzzle.


#include "stdio.h"
int main()
{
int x = 5;
printf("%f",x);
return 0;
}

This program throws me the following warning:

double format, different type arg (arg 2)


and the output is 0.000000

What is this?
His arguement was like this. Though my compiler allocates 4 bytes for both integer and float datatypes, why am I not being able to retrieve the same value if I interchange the types?

Yes, very good question.

The explanation goes like this.

The data will be retrieved from a variable in the way it is stored. If you retrieve it in a way different from the way it is stored, you will not be able to get the same value you have stored.

Lets be a bit more clear.

I am going to show you how the variables are stored in the memory.

Observe the following program.

#include "stdio.h"
int main()
{
int x=800;
int *x_int_ptr = &x;
unsigned char *x_char_ptr = (unsigned char *)x_int_ptr;
printf("%x %x %x %x",*(x_char_ptr+3),*(x_char_ptr+2),*(x_char_ptr+1),*(x_char_ptr));
return 0;
}


The output is 0 0 3 20

What is this?
Yes, the integer will be stored in the local memory like this. The equivalent of Integer Decimal 800 is Integer Binary 0b0000 0000 0000 0000 0000 0011 0010 0000.
But a character can store only 8 bits. So the higher byte 0000 0011 is stored as 3 in the second LS byte of output and the lower byte 0010 0000 which is 20 is stored in the first LS byte.

An integer 800 is stored like this.

Lets see how a float is stored.


#include "stdio.h"
int main()
{
float x=800;
float *x_int_ptr = &x;
unsigned char *x_char_ptr = (unsigned char *)x_int_ptr;
printf("%x %x %x %x",*(x_char_ptr+3),*(x_char_ptr+2),*(x_char_ptr+1),*(x_char_ptr));
return 0;
}



The ouput is 44 48 0 0

If we retrieve this value like an integer, how can we expect a correct result?
Let me justify the output 44 48 0 0.
This storage in memory is based on IEEE754 standard.

Just go the following link.
http://babbage.cs.qc.edu/IEEE-754/32bit.html

There you will find a calculator which takes this hex value as input and computes the decimal value that is given as input.

Just type 44480000 in field adjacent to Hexadecimal Representation, and you will be seeing the 800 in the field adjacent to Decimal Value Entered:.

So you need to be very careful while storing and retrieving data.


Isnt this program weird?

Monday, December 10, 2007

Interesting C Program -20

Today, when I was studying about preprocessing stuff in C Programs, I thought of trying out something different. I wrote the following C program.


#define a #include"stdio.h"
#define b main()
#define c {
#define d printf("hello world\n");
#define e }
a
b
c
d
e


Will it work?

No. It didnt worked!!!

I got the following error.

syntax error at '#' token
syntax error before string constant


What exactly could be the reason?

Lets analyse it step by step, from the DOS prompt. The following steps will work only when your path variables are correct. In order to correct them you must tweak in the Environment variables.


First lets just preprocess it.

Type the following command in the DOS Prompt


gcc -E main.c>main.i

The output of preprocessing has been redirected to the main.i.

When I opened main.i, I found the following.
----------main.i file starts here---------------------

# 1 "src\\main.c"
# 1 ""
# 1 ""
# 1 "src\\main.c"
# 58 "src\\main.c"
#include"stdio.h"
main()
{
printf("hello world\n");
}


----------main.i file ends here-----------------------


Hurray!!! I found out the problem.
After preprocessing, all the #defines has been replaced by their respective counter parts. But the only #include remains as it is. It didnot get replaced by the #include "stdio.h" file. This is causing the error.

Now let me make some modifications.


#define b main()
#define c {
#define d printf("hello world\n");
#define e }
#include "stdio.h"
b
c
d
e

Now it is compiling.

Is it correct? Lets check it out.

Now run the same command

gcc -E main.c>main.i

Observe the main.i file
My god, I am getting a very big main.i file.

If you see that file, the stdio.h file has been pasted there.

The conclusion is that the input to a compiler should not have #'s in the code. All #'s should be removed at the preprocessing stage itself.

A compiler doesnot know #.

Isnt this program weird? ;)

Wednesday, December 5, 2007

Interesting C Program -19

Hey,
Its long since my last post. I am here, with a very unique program.

Observe the output of the following C program
CASE:1

void func(void);
int main()
{
if(0)
func();
return 0;
}

Does this compile? (Yes/No). The answer depends on the compiler you are using. In some compilers this will compile without any errors. How come? "func()" is not defined anywhere. How come it is running?

Some smart compilers have that intelligence to compile such codes. This program runs, because "if(0)" is never going to be true. So the statement that follows is will never be executed. So, it dont even bother to search where the "func" function has been defined.

Ok, lets play around with the same program. Try out the following program.
CASE:2
void func(void);
int x = 0;
int main()
{
if(x)
func();
return 0;
}

Alas! this is throws the following errors.


Compiling source file(s)...
file_2.c
Linking...
C:\Documents and Settings\Administrator\Desktop\CTIPS\my_proj\Debug\file_2.o(.text+0x28): In function `main':
C:\Documents and Settings\Administrator\Desktop\CTIPS\my_proj\file_2.c:65: undefined reference to `func'



Why the hell it is throwing linker errors?

Lets do some more modifications and try.

Try out the following program.
CASE:3

void func(void);
const int x = 0;
int main()
{
if(x)
func();
return 0;
}


Again this throws the same error.
Is there any way of running this program?
Yes, there are ways.

There is a small tweaking you need to do in the compiler settings.

Lets try out that.

I am using MingWStudio. Try out similar things in your compiler or the Makefile.

1. Go to Project->Settings.
2. Go to Compile tab
3. By default the Optimization level will be None.
4. Change the Optimization to Level 1 or Level 2 or Level 3 or Minimum Size.
5. Give OK.
CASE:4
Now Clean the program to remove some previous configuration and then build.

This will definitely run.

The explanation goes like this.
In CASE:1, since mine is a smart compiler, this will be compiled without any errors.
I am working on CASE:2, CASE:3 and CASE:4.

Meanwhile if somebody knows why CASE:2 and CASE:3 didnt work and CASE:4 worked, please do comment me.

Friday, November 2, 2007

Sorting Algorithm - 2 (Shaker Sort)

A slightly improved version of BUBBLE SORTING.


void shaker_sort(char *str,int count)
{
int i,exchange=0;
do{
exchange = 0;
for(i=1;i<count-1;i++)
{
if(str[i]>str[i+1])
{
exchange = 1;
swap_items(&str[i],&str[i+1]);
}
}
for(i=count-1;i>0;i--)
{
if(str[i-1]>str[i])
{
exchange = 1;
swap_items(&str[i-1],&str[i]);
}
}
}while(exchange);
}
void swap_items(char *a,char *b)
{
(*a)^=(*b)^=(*a)^=(*b);
}

Sorting Algorithm - 1 (BUBBLE SORT)

A very primitive, simple and Well known Sorting algorithm.


void bubble_sort(char *str, int count)
{
int i,j;
for(i=0;i<count;i++)
{
for(j=count-1;j>i;j++)
{
if(str[j-1]>str[j])
{
swap_terms(&str[i],&str[j]);
}
}
}
}

void swap_terms(char *a,char *b)
{
(*a)^=(*b)^=(*a)^=(*b);
}

Monday, October 29, 2007

Interesting C Program -18

Hi all,
Observe the output of the following program.


#include "stdio.h"
#define DPRINTI(X) printf("\n%s = %d \n",#X,X)
#define DPRINTF(X) printf("\n%s = %f\n",#X,X)
#define DPRINTC(X) printf("\n%s = %c\n",#X,X)
int main()
{
double x = 100.1;
int y = 5;
char z = 'a';
void *p;

p = &z;
DPRINTI(sizeof(*(char *)p));
DPRINTC(*(char *)p);
DPRINTI(p);

p = &y;
DPRINTI(sizeof(*(int *)p));
DPRINTI(*(int *)p);
DPRINTI(p);

p = &x;
DPRINTI(sizeof(*(double *)p));
DPRINTF(*(double *)p);
DPRINTI(p);

return 0;
}


The output is something like the following:


sizeof(*(char *)p) = 1

*(char *)p = a

p = 2293635

sizeof(*(int *)p) = 4

*(int *)p = 5

p = 2293636

sizeof(*(float *)p) = 8

*(double *)p = 100.100000

p = 2293640



Explanation goes like this.

Initially a pointer has been initialized of type void * (generic pointer). We are type casting that pointer p to point a location in which a character is stored. Then we are typecasting that pointer p to point a location in which an integer is stored. Later, we are again type casting that pointer p to point a location in which a float is stored. This program runs without any errors.
The character variable is stored in 2293635 location (Size is 1 byte), ie 2293635.
The Integer variable is stored in 2293636 location (Size is 4 bytes), ie 2293636, 2293637, 2293638 and 2293639.
The Float variable is stored in 2293640 location (Size is 8 bytes), ie 2293640, 2293641, 2293642, 2293643, 2293644, 2293645, 2293646 and 2293647.
Every thing seems simple.

Hey wait wait. How can Life be so simple?

Lets see what happens when the following code is executed?


#include "stdio.h"
#define DPRINTI(X) printf("\n%s = %d \n",#X,X)
#define DPRINTF(X) printf("\n%s = %f\n",#X,X)
#define DPRINTC(X) printf("\n%s = %c\n",#X,X)
int main()
{
double x = 100.1;
int y = 5;
char z = 'a';
void *p;

p = &x;
DPRINTI(sizeof(*(double *)p));
DPRINTF(*(double *)p);
DPRINTI(p);

p = &y;
DPRINTI(sizeof(*(int *)p));
DPRINTI(*(int *)p);
DPRINTI(p);

p = &z;
DPRINTI(sizeof(*(char *)p));
DPRINTC(*(char *)p);
DPRINTI(p);

return 0;
}

The output is something like this:


The output is something like the following:


sizeof(*(float *)p) = 8

*(double *)p = 100.100000

p = 2293640

sizeof(*(int *)p) = 4

*(int *)p = 5

p = 2293636

sizeof(*(char *)p) = 1

*(char *)p = a

p = 2293635



Dont you see something weird in the output?

The addresses of float, int, and char should be respectively,2293635, 2293643 and 2293647. ie. the starting address should be 2293635. From there float occupies 8 bytes. The next 4 bytes is occupied by Integer (2293643, 2293644,2293645 and 2293646 and the next 1 byte is occupied by character variable, which is 2293647.
But that is not happening.

Can anybody comment me with the reason for that?

Wednesday, October 24, 2007

Interesting C Program -17

Hey!!!
This code converts the decimal number into binary, decimal, octal and hexadecimal number systems. Here "pow()" function is used. Since pow() function returns float, the values are typecasted.
Note: Never use a^b for "a raised to the power of b". This will do the EXOR operation.
Try using pow(base,power) function.


#include "stdio.h"
#include "math.h"
/*----------#defines starts here----------*/
#define DECIMAL 10
#define BINARY 2
#define OCTAL 8
#define HEXADECIMAL 16
#define DIGITS_DECIMAL 5
#define DIGITS_BINARY 16
#define DIGITS_OCTAL 3
#define DIGITS_HEXADECIMAL 3
/*-----------#defines ends here-----------*/
/* FUNCTION DECLARATIONS STARTS HERE */
char *tobinary(int x);
char *todecimal(int x);
char *tooctal(int x);
char *tohexadecimal(int x);
/* FUNCTION DECLARATIONS ENDS HERE */
int main()
{
int x;
char *y;
printf("ENTER THE VALUE TO CONVERT:\t\t");
scanf("%d",&x);
y=tobinary(x);
printf("\nBINARY:\t\t%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c"\
,y[0],y[1],y[2],y[3],y[4],y[5],y[6],y[7],y[8],y[9],y[10],\
y[11],y[12],y[13],y[14],y[15]);
y=todecimal(x);
printf("\nDECIMAL:\t%c %c %c %c %c",y[0],y[1],y[2],y[3],y[4]);
y=tooctal(x);
printf("\nOCTAL:\t\t%c %c %c",y[0],y[1],y[2]);
y=tohexadecimal(x);
printf("\nHEXADECIMAL:\t%c %c %c",y[0],y[1],y[2]);

return 0;
}
/* FUNCTION DEFINITIONS STARTS HERE */
char *todecimal(int x)
{
char y[3];
int i;
for(i=0;i<DIGITS_DECIMAL;i++)
{
y[i] = ((x/(int)pow(DECIMAL,(DIGITS_DECIMAL-i-1)))%DECIMAL)+0x30;
}
return y;
}

char *tobinary(int x)
{
char y[8];
int i;
for(i=0;i<DIGITS_BINARY;i++)
{
y[i] = ((x/(int)pow(BINARY,(DIGITS_BINARY-i-1)))%BINARY)+0x30;
}
return y;
}
char *tooctal(int x)
{
char y[3];
int i;
for(i=0;i<DIGITS_OCTAL;i++)
{
y[i] = ((x/(int)pow(OCTAL,(DIGITS_OCTAL-i-1)))%OCTAL)+0x30;
}
return y;
}
char *tohexadecimal(int x)
{
char y[3];
int i;
for(i=0;i<DIGITS_HEXADECIMAL;i++)
{
y[i] = ((x/(int)pow(HEXADECIMAL,(DIGITS_HEXADECIMAL-i-1)))%HEXADECIMAL)+0x30;
if(y[i]==0x3A) y[i] =0x41;
if(y[i]==0x3B) y[i] =0x42;
if(y[i]==0x3C) y[i] =0x43;
if(y[i]==0x3D) y[i] =0x44;
if(y[i]==0x3E) y[i] =0x45;
if(y[i]==0x3F) y[i] =0x46;


}
return y;
}
/* FUNCTION DEFINITIONS ENDS HERE */

Monday, August 20, 2007

Interesting C Program -16

Can u write a C program to swap two integers that does not use a temporary variable (or that uses only two variables to be swapped)?


Here goes an implementation:


#include "stdio.h"
int main()
{
int a=1,b=3;
printf("BEFORE SWAPPING : a=%d & b=%d\n",a,b);
a^=b^=a^=b;
printf("AFTER SWAPPING : a=%d & b=%d\n",a,b);
}


The output looks something like this:

BEFORE SWAPPING : a=1 & b = 3
AFTER SWAPPING : a=3 & b = 1

Looks good isn't it?

Sunday, August 19, 2007

Interesting C Program -15

Atlast, Here is my implementation of Pascal Triangle!!!

/*PASCAL TRIANGLE*/
#include"stdio.h"
int factorial(int);
int combination(int,int);
int main()
{
int rows,i,j;
printf("ENTER THE NUMBER OF ROWS:\t");
scanf("%d",&rows);
printf("\n---------------------------------------------------------\
------------------\n");
printf(" PASCAL TRIANGLE WITH %d ROWS \ ",rows);
printf("\n-----------------------------------------------------------\
----------------\n");
for(i=1;i<=rows;i++)
{
for(j=0;j<=i;j++)
{
printf("%d\t",combination(i,j));
}
//printf("\n");
printf("\n---------------------------------------------------------------\
------------\n");
}
}
int factorial(int x)
{
if(x<2)
return 1;
else
{
return x*factorial(x-1);
}
}
int combination(int n,int r)
{
int y;
y=factorial(n)/(factorial(r)*factorial(n-r));
return y;
}


The Output looks like this

ENTER THE NUMBER OF ROWS: 5

---------------------------------------------------------------------------
PASCAL TRIANGLE WITH 5 ROWS
---------------------------------------------------------------------------
1 1
---------------------------------------------------------------------------
1 2 1
---------------------------------------------------------------------------
1 3 3 1
---------------------------------------------------------------------------
1 4 6 4 1
---------------------------------------------------------------------------
1 5 10 10 5 1
---------------------------------------------------------------------------

Thursday, August 2, 2007

Interesting C Program -14

Just see the output of the following C program. The output looks bit weird. Isnt it?


#include "stdio.h"
#define DPRINTF(x) printf("%s = %d\n",#x,x);

int main()
{
int x[20];
int *p,*q;
p=&x[5];
q=&x[9];
DPRINTF(p);
DPRINTF(q);
DPRINTF(q-p);
}



The output is


p = 2293580
q = 2293596
q-p = 4

q-p should be 16. But it gives 4. why?



The explanation goes like this.


Lets take a real life example.

Say you took 9 dozens of apples. You returned 5 dozens of apples. Then how many dozens of apples do you have? 4 dozens isnt it? You will not say 48 apples.

Similar is the case here. x[9] is stored in 2293596 address location and x[5] is stored in 2293580. p and q are integer pointers, each occupying 4 bytes. Now when you display the value of p and q, they will be 2293580 and 2293596 respectively. But if you ask for difference, it will be 4.
Inshort, 9 integer pointers - 5 integer pointers = 4 integer pointers.


Now just try this program:



#include "stdio.h"
#define DPRINTF(x) printf("%s = %d\n",#x,x);

int main()
{
int x[20],y,z;
int *p,*q;
p=&x[5];
q=&x[9];
DPRINTF(p);
DPRINTF(q);
DPRINTF(q-p);
y = p;
z = q;
DPRINTF(y);
DPRINTF(z);
DPRINTF(z-y);
}

The output is like this:

p = 2293580
q = 2293596
q-p = 4
y = 2293580
z = 2293596
z-y = 16


If you see the difference between z and y, you will get 16.

I think now no explanation is required now.

Interesting C Program -13

Hey!!! Now u can change the color of the output window (DOS window). How?

Just try the following program:


#include "stdio.h"
#include "string.h"
#include "stdlib.h"
main()
{
int i=0;
for(i = 0;i<3;i++)
{
char x[] = "color ";
(i==0)?strcat(x,"0F"):((i==1)?strcat(x,"1E"):((i==2)?strcat(x,"2D")\
:strcat(x,"3C")));
system(x);
system("pause");
}
}


Your output window looks colorful right?

Interesting C Program -12

Can you write a simple "Hello World" Program that doesnot use semicolon?
Here is an implementation!!!


#include "stdio.h"
int main()
{
if(printf("Hello World")){}
}

Friday, July 13, 2007

Interesting C Program -11

Want to know my name?



char a[5][6] = {
{0xe,0x6,0x8,0x6,0x7,0xe},
{0x9,0x9,0x8,0x9,0x2,0x4},
{0xe,0xf,0x8,0xf,0x2,0x4},
{0x9,0x9,0x8,0x9,0xa,0x4},
{0xe,0x9,0xe,0x9,0x4,0xe}
};
m[4]={0x8,0x4,0x2,0x1};
int main()
{
int i,j,k;
do
{
j=0;
do
{
k=0;
do
{
(a[i][j]&m[k])?printf("#"):printf(" ");
}while(++k<4);
printf(" ");
}while(++j<6);
printf("\n");
}while(++i<5);

}

Search Google

Books that I refer to...

  • The Complete Reference C, Fourth Edition
  • The C Programming Language