We can use typecast operator to convert the type of value returned by a pointer dereference expression to another suitable type. For example, if pa is a pointer to a variable a of type int, we can use typecast as (double) *pa to convert the integer value of *pa to type double.
The C language also allows us to use typecast to convert the type of a pointer, as in (char *) pa. This converts the pointer pa, which is assumed to be a pointer to int, to char *, i. e., a character pointer. Such typecasts are essential and are commonly used while dealing with void pointers. However, it should be used very carefully in other situations as it may lead to erroneous situations. For example, the expression *pa interprets the contents of two (or four) consecutive memory locations pointed to by pointer pa as an integer, whereas the expression * ( (char *) pa) interprets the contents of only one byte pointed to by pa, i. e., some part of integer value, as a character. Nevertheless, there are situations where this kind of conversion is useful, as illustrated in Example.
The sizeof operator, when used with a pointer variable, as in sizeof (pa), gives us the size of a pointer variable, i. e., memory required for its storage in bytes.
Example of function to print binary representation of numbers
Consider that we wish to print binary representations of numbers of different data types (int, short int, float, long double, etc.). One approach to do this is to write a separate function for each data type. However, this is tedious and time-consuming. Instead, we can write a single function named print_binary the as shown below.
void print_binary(unsigned char *pc, int n)
{
int i;
for(i = n – 1; i >= O; i–) /* process bytes from MSB to LSB */
print_char_bits(pc[i]); /* print a byte in binary */
}
To handle different data types and sizes, this function accepts an unsigned character pointer to the variable to be printed and its size in bytes. The for loop is set up to process individual bytes starting with the most significant byte (which is the last byte on most computers as the numbers are stored starting with the least significant byte). The bit pattern of each byte is printed by calling the print_ char_ bits function given below.
void print_char_bits(unsigned char c)
{
int i;
unsigned char mask= Ox80; /* i.e. mask = 10000000 (binary) */
for(i = 7; i >= 0; i–)
{
printf(“%c”, (c & mask? ‘1’: ‘0’)); /*print bit at position i*/
mask >>= 1; /* shift ‘1’ in mask to right side */
}
printf (” “) ;
}
This function accepts a byte as an unsigned character and uses a for loop to process individual bits in a character starting with the most significant bit (i. e., bit 7). A mask is used to separate individual bits. It is initialized to Ox80 (i.e., 1000 00002) before the loop and in each iteration, .the bit pattern is shifted to the right by one position. The bit-wise and (&) operator is used along with the conditional operator to print a bit as
printf(“%c”, (c & mask? ‘1’ : ‘0’)); /*print bit at position i */
Note that to simplify the code, we can eliminate variable i and use variable mask as the loop variable as shown below.
void print_char_bits(unsigned char c)
{
unsigned char mask;
for(mask = Ox80; mask> 0; mask>>= 1) /* process bits MSB to LSB */
printf(“%c”, (c & mask? ‘1’ : ‘0’)); /*print current bit*/
printf(” “);
}
The main function used to print the binary representations of two numbers (of type short int and float) is given below.
int main()
{
short int a = 6;
float x = 1.23;
printf (“short int : %4hd Binary: “, a);
print_binary((unsigned char*) &a, sizeof(a));
printf(“\nfloat : %0.2f Binary: “, x);
print_binary( (unsigned char *).&x, sizeof(x));
return O;
}
Observe how the address of the variable to be printed is typecast to unsigned char *.The program output is given below.
short int : 6 Binary: 00000000 00000110
float : 1.23 Binary: 00111111 10011101 01110000 10100100