Data types are provided to store various types of data that is processed in real life. A student's record might contain the following data types: name, roll number, and grade percentage. For example, a student named Anil might be assigned roll number 5 and have a grade percentage of 78.67. The roll number is an integer without a decimal point, the name consists of all alpha characters, and the grade percentage is numerical with a decimal point. C supports representation of this data and gives instructions or statements for processing such data. In general, data is stored in the program in variables, and the kind of data the variable can have is specified by the data type. Using this example, grade percentage has a float data type, and roll number has an integer data type. The data type is attached to the variable at the time of declaration, and it remains attached to the variable for the lifetime of the program. Data type indicates what information is stored in the variable, the amount of memory that can be allocated for storing the data in the variable, and the available operations that can be performed on the variable. For example, the operation S1 * S2, where S1 and S2 are character strings, is not valid for character strings because character strings cannot be multipled.
Program
// the program gives maximum and minimum values of data type #include main() { int i,j ;// A i = 1; while (i > 0) { j = i; i++; } printf ("the maximum value of integer is %d ",j); printf ("the value of integer after overflow is %d ",i); }
Points to Remember
C supports various data types for processing information. There is a family of integer data types and floating-point data types. Characters are stored internally as integers, and they are interpreted according to the character set. The most commonly used character set is ASCII. In the ASCII character set, A is represented by the number 65.
Program/Examples
The data type families are as follows:
Integer family char data type int data type short int data type long int data type
These data types differ in the amount of storage space allocated to their respective variables. Additionally, each type has two variants, signed and unsigned, which will be discussed later.
Float family (real numbers with decimal points) Float data type Double data type
(ANSI has also specified long double, which occupies the same storage space as double)
Points to Remember
Integer data types are used for storing whole numbers and characters. The integers are internally stored in binary form.
Program/Example
Here is an example that shows how integers are stored in the binary form.
Number =13
Each 1 or 0 is called a bit, thus the number 13 requires 4 bits.
In the same way, the number 130 is 1000 0010 in binary.
If the general data type is char, 8 bits are allocated. Using 8 bits, you can normally represent decimal numbers from 0 to 255 (0000 0000 to 1111 1111). This is the case when the data type is unsigned char. However, with signed char, the leftmost bit is used to represent the sign of the number. If the sign bit is 0, the number is positive, but if it is 1, the number is negative.
Binary representation of the following numbers in signed char is as follows:
Number = 127 Binary representation = 0111 1111 (leftmost bit is 0, indicating positive.)
Number = −128 Binary representation = 1000 0000 (leftmost bit is 1, indicating negative.)
The negative numbers are stored in a special form called "2's complement". It can be explained as follows:
Suppose you want to represent −127:
1000 0000 + 1 ------------- 1000 0001 (−127)
Thus in the signed char you can have the range −128 to +127, i.e. (−28 to 28−1).
The binary representation also indicates the values in the case of overflow. Suppose you start with value 1 in char and keep adding 1. You will get the following values in binary representation:
0000 0001 (1) 0111 1111 (127) 1000 0000 (-128) 1000 0001 (-127)
In the case of unsigned char you will get
0000 0001 (1) 0111 1111 (127) 1000 0000 (128) 1000 0001 (129) 1111 1111 (255) 0000 0000 (0)
This concept is useful in finding out the behavior of the integer family data types.
The bytes allocated to the integer family data types are (1 byte = 8 bits) shown in Table 2.1.
Data Type |
Allocation |
Range |
---|---|---|
signed char |
1 byte |
−27 to 27−1 (−128 to 127) |
Unsigned char |
1 byte |
0 to 28−1 (0 to 255) |
short |
2 bytes |
−215 to 215 −1 (−32768 to 32767) |
Unsigned short |
2 bytes |
0 to 216 −1 (0 to 65535) |
long int |
4 bytes |
231 to 231−1 (2,147,483,648 to 2,147,483,647) |
int |
2 or 4 bytes depending on implementation |
Range for 2 or 4 bytes as given above |
Points to Remember
Overflow means you are carrying out an operation such that the value either exceeds the maximum value or is less than the minimum value of the data type.
Program
// the program gives maximum and minimum values of data type #include main() { char i,j ; i = 1; while (i > 0) // A { j = i; // B i++; // C } printf ("the maximum value of char is %d ",j); printf ("the value of char after overflow is %d ",i); }
Explanation
Points to Remember
Alpha characters are stored internally as integers. Since each character can have 8 bits, you can have 256 different character values (0–255). Each integer is associated with a character using a character set. The most commonly used character set is ASCII. In ASCII, "A" is represented as decimal value 65, octal value 101, or hexadecimal value 41.
Explanation
If you declared C as a character as
char c;
then you can assign A as follows:
c = 'A'; c = 65; c = 'x41'; // Hexadecimal representation c = '101'; // Octal representation
You cannot write c = ‘A’ because ‘A’ is interpreted as a string.
Escape Sequence
Certain characters are not printable but can be used to give directive to functions such as printf. For example, to move printing to the next line you can use the character " ". These characters are called escape sequences. Though the escape sequences look like two characters, each represents only a single character.
The complete selection of escape sequences is shown here.
a |
alert (bell) character |
\ |
backslash |
|
backspace |
? |
question mark |
f |
form feed |
’ |
single quote |
|
new line |
" |
double quote |
|
carriage return |
ooo |
octal number |
|
horizontal tab |
xhh |
hexadecimal number |
v |
vertical tab |
Points to Remember
You can represent a number by using the octal number system; that is, base 8. For example, if the number is 10, it can be represented in the octal as 12, that is, 1*81 + 2*80.
Explanation
When octal numbers are printed they are preceeded by "%0".
Hexadecimal numbers use base 16. The characters used in hexadecimal numbers are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F. For example, if the decimal number is 22, it is represented as 16 in the hexadecimal representation: 1*161 + 6*160 .
Explanation
You can print numbers in hexadecimal form by using the format "0x".
Floating-point numbers represent two components: one is an exponent and the other is fraction. For example, the number 200.07 can be represented as 0.20007*103, where 0.2007 is the fraction and 3 is the exponent. In a binary form, they are represented similarly. There are two types of representation: short or single- precision floating-point number and long or double-precision floating-point number. short occupies 4 bytes or 32 bits while long occupies 8 bytes or 64 bits.
Program/Example
In C, short or single-precision floating point is represented by the data type float and appears as:
float f ;
A single-precision floating-point number is represented as follows:
Here the fractional part occupies 23 bits from 0 to 22. The exponent part occupies 8 bits from 23 to 30 (bias exponent, that is, exponent + 01111111). The sign bit occupies the 31st bit.
Suppose the decimal number is 100.25. It can be converted as follows:
Since the number is positive, the sign bit is 0. The significant, or fractional, part is:
1001 0001 0000 0000 0000 000
Note that up until the fractional part, only those bits that are on the right side of the decimal point are present. The 0s are added to the right side to make the fractional part take up 23 bits.
Special rules are applied for some numbers:
The range of the float data type is 10−38 to 1038 for positive values and −1038 to −10−38 for negative values.
The values are accurate to 6 or 7 significant digits depending on the actual implementation.
Conversion of a number in the floating-point form to a decimal number
Suppose the number has the following components:
Since the exponent is bias, find out the unbiased exponent.
Represent the number as 1.1001001*24
Represent the number without the exponent as 11001.001
Convert the binary number to decimal: −25.125
For double precision, you can declare the variable as double d; it is represented as
Here the fractional part occupies 52 bits from 0 to 51. The exponent part occupies 11 bits from 52 to 62 (the bias exponent is the exponent plus 011 1111 1111). The sign bit occupies bit 63. The range of double representation is +10−308 to +10308 and −10308 to −10−308. The precision is to 10 or more digits.
Formats for representing floating points
Following are the valid representions of floating points:
0.23456 2.3456E-1 .23456 .23456e-2 2.3456E-4 -.232456E-4 2345.6 23.456E2 -23456 23456e3
Following are the invalid formats:
e1 2.5e-.5 25.2-e5 2.5.3
You can determine whether a format is valid or invalid based on the following rules:
d.d, d., .d, d, where d is a set of digits.
You can use the format %f for printing floating numbers. For example, printf("%f ", f);
%f prints output with 6 decimal places. If you want to print output with 8 columns and 3 decimal places, you can use the format %8.3f. For printing double you can use %lf.
Floating-point computation may give incorrect results in the following situations:
Points to Remember
Type conversion occurs when the expression has data of mixed data types, for example, converting an integer value into a float value, or assigning the value of the expression to a variable with different data types.
Program/Example
In type conversion, the data type is promoted from lower to higher because converting higher to lower involves loss of precision and value.
For type conversion, C maintains a hierarchy of data types using the following rules:
These general rules are accompanied by specific rules, as follows:
Forced conversion occurs when you are converting the value of the larger data type to the value of the smaller data type, for example, if the declaration is char c;
and you use the expression c = 300; Since the maximum possible value for c is 127, the value 300 cannot be accommodated in c. In such a case, the integer 300 is converted to char using forced conversion.
Program/Example
In general, forced conversion occurs in the following cases:
Forced conversion is performed according to following rules:
In the case of type conversion, lower data types are converted to higher data types, so it is better to a write a function using higher data types such as int or double even if you call the function with char or float. C provides built-in mathematical functions such as sqrt (square root) which take the argument as double data type. Suppose you want to call the function by using the integer variable ‘k’. You can call the function
sqrt((double) n)
This is called type casting, that is, converting the data type explicitly. Here the value ‘k’ is properly converted to the double data type value.
Points to Remember
Type casting is used when you want to convert the value of a variable from one type to another. Suppose you want to print the value of a double data type in integer form. You can use type casting to do this. Type casting is done to cast an operator which is the name of the target data type in parentheses.
Program
#include main() { double d1 = 123.56; \ A int i1=456; \ B printf("the value of d1 as int without cast operator %d ",d1); \ C printf("the value of d1 as int with cast operator %d ",(int)d1); \ D printf("the value of i1 as double without cast operator %f ",i1); \ E printf("the value of i1 as double with cast operator %f ",(double)i1); \ F i1 = 10; printf("effect of multiple unary operator %f ",(double)++i1); \ G i1 = 10; \ H //printf("effect of multiple unary operator %f ",(double) ++ -i1); error \ I i1 = 10; printf("effect of multiple unary operator %f ",(double)- ++i1);\ J i1 = 10; \ K printf("effect of multiple unary operator %f ",(double)- -i1); \ L i1 = 10; \ M printf("effect of multiple unary operator %f ",(double)-i1++); \ N }
Explanation
Points to Remember
Part I - C Language
Part II - Data Structures
Part III - Advanced Problems in Data Structures