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 */

Search Google

Books that I refer to...

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