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.

Search Google

Books that I refer to...

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