egsoftweb@gmail.com
 facebook.com/egsoftweb

Welcome to EGSoftWeb

Programming
Blogs and Tutorials

Blogs on programming, technology, programming tutorials & code snippets. Share your technical skill and we will publish it.

Desktop
Application

Antivirus, encryption/decryption, folder locking tools and miscellaneous desktop applications.

Programming Library

C++ drawing library for plotting shape in 2D, 3D, animation and many other functions.

Android
Application

Just gambling around the android programming and need to make a few useful android applications and tricky android puzzle games.

Type Conversion & Casts in C

 c tutorials |  Admin

Type Conversion:

When constants and variables of different types are mixed in an expression, they are all converted to the same type. The compiler converts all operands up to the type of the largest operand, which is called “type promotion”. First, all char and short int values are automatically elevated to int. This process is called “integral promotion”. (In C99, an integer promotion may also result in a conversion to unsigned int) Once this step has been completed, all other conversions are done operation by operation in the following type promotion order.

 

long double

double

float

unsigned long

long

unsigned int

int

char

Type Promotion Order:

 

There is one additional special case: If one operand is long and the other is unsigned int, and if the value of the unsigned int cannot be represented by a long, both operands are converted to unsigned long.

Once these conversion rules have been applied, each pair of operands is of the same type, and the result of each operation is the same as the type of both operands.

  

For example:

// example type conversion

#include <stdio.h>

int main()

{

     char c = `c`; /* ascii value of c is 99 */

     int i = 5;

     float f =7.7f;

     double d = 3.12334;

 

     /*let we print the expression

     ((c / i) + (f*d) - (f + i)) in different formats

     */

     printf("%d", ((c / i) + (f*d) - (f + i)));

     printf("\n");

     printf("%f", ((c / i) + (f*d) - (f + i)));

     getchar();

     return 0;

}

 

/* output

 

396452324

30.349718

*/

 

/*

Here in the expression ((c / i) + (f*d) - (f + i)),

(c/i) converted into int, (f*d) converted in to double

& (f+i) converted in float.The result of int, double &

float is double and so the final result is in double.

*/

  

Casts:

We can force an expression to be of a specific type by using a cast. General form of a cast is

(type) expression

where type is a valid data type. For example, to cause the expression x/2 to evaluate to type float, we write

(float) x/2

 

Casts are technically operators. As an operator, a cast is unary and has the same precedence as any other unary operator.

 

//example using cast

#include <stdio.h>

int main()

{

     int i = 159;

     printf("half of i is %f", (float)i / 2);

     getchar();

     return 0; 

}

 

/*

here without the cast (float), only an integer

division would have been performed. The cast

ensures that the fractional part of the answer

is displayed.

*/

Operators in C

 c tutorials |  Admin

There are four main classes of operators:

arithmetic,

relational,

logical,

bitwise

 

In addition, there are some special operators, such as the assignment operator, for particular tasks.

 

Assignment Operator (In Short): The general form of the assignment operator is

variable_name = expression;

 

Arithmetic Operators:

Operator

Action

+

Addition, also unary plus

-

Subtraction, also unary minus

*

Multiplication

/

Division

%

Modulus

++, --

Increment & Decrement

 

//example using arithmatic operators

#include <stdio.h>

int main()

{

     int a = 20, b = 10;

 

     int add = a + b;

     int sub = a - b;

     int mul = a * b;

     int div = a / b;

     int rem = a % b;

 

     int u_plus = +a;

     int u_minus = -a;

 

     printf(" + result: %d\n", add);

     printf(" - result: %d\n", sub);

     printf(" * result: %d\n", mul);

     printf(" / result: %d\n", div);

     printf(" %% result: %d\n", rem);

     printf(" unary + result: %d\n", u_plus);

     printf(" unary - result: %d\n", u_minus);

 

     getchar();

     return 0;

}

 

 

The Increment and Decrement Operators:

C includes two useful operators that simplify two common operations. These are the increment and decrement operators, ++ and --.

x = x+1; is the same as ++x;

x = x–1; is the same as --x;

Both the increment and decrement operators may either precede (prefix) or follow (postfix) the operand. For example,

x = x+1; can be written ++x; or x++;

 

Difference between prefix & postfix increment or decrement operators:

When an increment or decrement operator precedes its operand, the increment or decrement operation is performed before obtaining the value of the operand for use in the expression. If the operator follows its operand, the value of the operand is obtained before incrementing or decrementing it. For example:

int x, y;

//then,

x = 10; y = ++x;

//sets x to 11 and y to 11. But,

 

x = 10; y = x++;

//sets x to 11 and y to 10.

 

Precedence of the arithmetic operators:

Highest

++     --

 

unary plus     unary minus

 

*     /     %    

Lowest

+     -

Operators on the same level of precedence are evaluated by the compiler from left to right Of course, we can use parentheses() to alter the order of evaluation. Parentheses force an operation, or set of operations, to have a higher level of precedence.

 

Relational and Logical Operators:

Relational Operators:

Operator

Action

> 

Greater than

>=

Greater than or equal

< 

Less than

<=

Less than or equal

==

Equal

!=

Not equal

 

Logical Operators:

Operator   

Action  

&&

AND

||

OR

!

NOT

All relational and logical expressions produce a result of either 1 or 0. We can use parentheses to alter the natural order of evaluation in a relational and/or logical expression.

 

// example using relational operators

#include <stdio.h>

void print(int val)

{

     printf(" %d\n", val);

}

int main()

{

     print(2 > 1);

     print(2 < 1);

     print(2 >= 1);

     print(2 <= 2);

     print(2 == 0);

     print(2 != 1);

     getchar();

     return 0;

}

 

//example using logical operators

#include <stdio.h>

void printLogics(int p, int q)

{

     printf("%d\t%d\t%d\t%d\t%d\n\n", p, q, p && q, p || q, !p);

}

 

int main()

{

     printf("p\tq\tp&&q\tp||q\t!p\n\n");

     printLogics(0, 0);

     printLogics(0, 1);

     printLogics(1, 1);

     printLogics(1, 0);

     getchar();

     return 0;

}

 

The relative precedence of the relational and logical operators:

Highest

!

 

>     >=     <     <=

 

==     !=      

 

&&

Lowest

||

 

Bitwise Operators:

Operator

Action

&

AND

|

OR

^

Exclusive OR (XOR)

~

One`s complement (NOT)

>> 

Shift right

<< 

Shift left

Bitwise operation refers to testing, setting, or shifting the actual bits in a byte or word, which correspond to the standard char and int data types and variants.

 

we cannot use bitwise operations on float, double, long double, void, or other more complex types. The bitwise AND, OR, and NOT (one`s complement) are governed by the same truth table as their logical equivalents, except that they work bit by bit.

 

The one`s complement operator, ~, reverses the state of each bit in its operand. That is, all 1`s are set to 0, and all 0`s are set to 1. The bitwise operators are often used in cipher routines. If we want to make a disk file appear unreadable, we have to perform some bitwise manipulations on it. One of the simplest methods is to complement each byte by using the one`s complement to reverse each bit in the byte.

original byte

0 1 0 1 0 1 1 0 0

after 1`s complement

1 0 1 0 1 0 0 1 1

after 2`s complement

0 1 0 1 0 1 1 0 0

we see that the second complement decodes the byte to its original value.

relational and logical operators always produce a result that is either 1 or 0, whereas the similar bitwise operations may produce any arbitrary value in accordance with the specific operation. The bit-shift operators, >> and <<, move all bits in a variable to the right or left as specified. The general form of the shift-right statement is

variable >> number of bit positions

 

The general form of the shift-left statement is

variable << number of bit positions

 

//example using bitwise AND,OR,XOR and One`s complement

#include <stdio.h>

void printBitwiseOperations(int p, int q)

{

     printf("%d\t%d\t%d\t%d\t%d\t%d\n\n", p, q, p&q, p | q, p^q, ~p);

}

int main()

{

     printf("p\tq\tp&q\tp|q\tp^q\t~p\n\n");

     printBitwiseOperations(0, 0);

     printBitwiseOperations(0, 1);

     printBitwiseOperations(1, 1);

     printBitwiseOperations(1, 0);

     getchar();

     return 0;

}

 

// example using bitwise shifting

/* A bit shift example. */

#include <stdio.h>

int main(void)

{

     unsigned int a, b, c, d, e;

     a = 1;

     /* left shifts */

     /* left shift a by 1, which is same as a multiply by 2 */

     b = a << 1;

     printf("Left shift %d: %d\n", a, b);

     c = b << 1;

     printf("Left shift %d: %d\n", b, c);

 

     /* right shifts */

     /* right shift i by 1, which is same as a division by 2 */

     d = b >> 1;

     printf("Right shift %d: %d\n", b, d);

     e = c >> 1;

     printf("Right shift %d: %d\n", c, e);

     getchar();

     return 0;

}

 

Assignment Operator (In Details):

The general form of the assignment operator is

variable_name = expression;

where an expression may be as simple as a single constant or as complex as we require. C uses a single equal sign to indicate assignment. The target, or left part or lvalue, of the assignment must be an object, such as a variable, that can receive a value. The term rvalue refers to expressions on the right side of an assignment and simply means the value of an expression.

 

Type Conversion in Assignments:

When variables of one type are mixed with variables of another type, a type conversion will occur. In an assignment statement, the type conversion rule is easy, The value of the right side (expression side) of the assignment is converted to the type of the left side (target variable).

 

Multiple Assignments:

we can assign many variables the same value by using multiple assignments in a single statement. For example,

int x, y, z;

x = y = z = 7;

 

Compound Assignments (shorthand assignment):

+=, -=, *=, /=, %= etc are Compound Assignments.

 

For example, x = x+5 can be written as x += 5;

 

Compound assignment operators exist for all the binary operators (those that require two operands). In general,

var = var operator expression

can be rewritten as

var operator = expression

 

The ? Operator (ternary operator):

A powerful and convenient operator that replaces certain statements of the if-then-else form.

 

Exp1 ? Exp2: Exp3;

means Exp1 is calculated and if Exp1 is 1 or(true) then Exp2 is calculated otherwise Exp3 is calculated.

for example we can assign a variable according to a condition like

variable = condition ? variable1 : variable2;

if condition is 1 then variable= variable1 otherwise variable= variable2

 

The & and * or address and pointer Operators:

A pointer is the memory address of an object. A pointer variable is a variable that is specifically declared to hold a pointer (or memory address) to an object of its specified type.

 

The first pointer operator is &, a unary operator that returns the memory address of its operand.

Note: a unary operator requires only one operand.

for example,

m = &var;

 

places into m the memory address of the variable var. This address is the computer`s internal location of the variable. It has nothing to do with the value of var. we can think of & as meaning 'the address of." Therefore, the preceding assignment statement means "m receives the address of var".

 

The second pointer operator is *, which is the complement of &. The * is a unary operator that returns the value of the object located at the address that follows it. For example, if m contains the memory address of the variable var,

 

v = *m;

places the value of var into v.

 

Think of * as meaning "at address." In this case, we could read the statement as "v receives the value at address m."

 

Variables that will hold pointers must be declared as such, by putting * in front of the variable name. This indicates to the compiler that it will hold a pointer to that type of variable. For example, to declare ch as a pointer to a character, we write:

char *ch;

 

It is important to understand that ch is not a character but a pointer to a character. There is a big difference. The type of data that a pointer points to, in this case char, is called the base type of the pointer. The pointer variable itself is a variable that holds the address to an object of the base type. Thus, a character pointer (or any type of pointer) is of sufficient size to hold an address as defined by the architecture of the host computer. It is the base type that determines what that address contains. We can mix both pointer and non-pointer variables in the same declaration statement. For example,

int x, *y, count;

declares x and count as integer types and y as a pointer to an integer type.

 

// simple example using address and pointer Operators.

#include <stdio.h>

int main(void)

{

     int target, source; 

     int *m;

     source = 2500;

     m = &source;

     target = *m;

     printf("%d", target);

     return 0;

}

 

The Compile-Time Operator sizeof:

sizeof is a unary compile-time operator that returns the length, in bytes, of the variable or  parenthesized type specifier that it precedes. For example,

// example sizeof operator

#include <stdio.h>

int main()

{

     double f = 3.1415;

     printf("%d ", sizeof f);

     printf("%d", sizeof(int));

     return 0;

}

 

to compute the size of a type, we must enclose the type name in parentheses. This is not necessary for variable names, although there is no harm done if we do so. sizeof is evaluated at compile time, and the value it produces is treated as a constant within your program.

 

The Comma Operator (,):

Comma operator strings together several expressions. The left side of the comma operator is always evaluated as void. This means that the expression on the right side becomes the value of the total comma-separated expression. For example,

x = (y=3, y+1);

Here the parentheses are necessary because the comma operator has a lower precedence than the assignment operator. The comma causes a sequence of operations. When you use it on the right side of an assignment statement, the value assigned is the value of the last expression of the comma-separated list.

 

The Dot (.) and Arrow (–>) Operators:

The . (dot) and the –> (arrow) operators access individual elements of structures and unions. Structures and unions are compound data types that may be referenced under a single name. The dot operator is used when working with a structure or union directly. The arrow operator is used with a pointer to a structure or union.

 

// example using dot (.) and arrow (->) operator

struct Circle

{

     float radius;

     float centerX;

     float centerY;

};

 

struct Circle c = { 2.0F, 4.5F, 6.7F };

 

struct Circle *p = &c; /* address of c into p */

 

#include <stdio.h>

int main()

{

     printf("Radius using dot operator= %f", c.radius);

     printf("\nRadius using arrow operator = %f", p->radius);

     getchar();

     return 0;

}

 

The [ ] and ( ) Operators:

Parentheses () are operators that increase the precedence of the operations inside them. For example,

int a,b,c,d,e;

a =2;

b=3;

c=4;

d=5;

e = ((a+b)*(c+d))*c;

Here expression (a+b) and (c+d) are calculated first then ((a+b)*(c+d)) and then ((a+b)*(c+d))*c;

Square brackets perform array indexing. Given an array, the expression within square brackets provides an index into that array.

for example:

// example using [] operator

#include <stdio.h>

int main(void)

{

     char pi[10] = {`3`,`.`,`1`,`4`,`1`,`5`,`2`,`9`,`6`,`\0`};

     printf("%s", pi);

     printf("\n");

     printf("%c", pi[1]);

     printf("\n");

     printf("%c", pi[9]);

     getchar();

     return 0;

}

 

Precedence of operators:

Highest

( )     [ ]     –>     .

 

!     ~     ++     --     -     (type)     *     &     sizeof