2.2 Data Types and Expressions

Standard Data Types

The type of a variable determines how much space it occupies in storage and how the bit pattern stored is interpreted. Standard data types in C are listed in the following table:

Table of Variable types
Variable Type Keyword Range Storage in Bytes
Character char -127 to 127 1
Unsigned character unsigned char 0 to 255 1
(Signed) integer int -32,768 to 32,767 2
Unsigned integer unsigned int 0 to 65,535 2
Short integer short -32,768 to 32,767 2
Unsigned short integer unsigned short 0 to 65,535 2
Long integer long -2,147,483,648 to 2,147,483,647 4
Unsigned long integerunsigned long 0 to 4,294,967,295 4
Single precision floating point float 1.2E-38 to 3.4E38, approx. range precision = 7 digits. 4
Double precision floating point double 2.2E-308 to 1.8E308, approx. range precision = 19 digits. 8

Declaration and Usage of Variables and Constants


A variable is an object of a specified type whose value can be changed. In programming languages, a variable is allocated a storage location that can contain data that can be modified during program execution. Each variable has a name that uniquely identifies it within its level of scope.

In C, a variable must be declared before use, although certain declarations can be made implicitly by content. Variables can be declared at the start of any block of code, but most are found at the start of each function. Most local variables are created when the function is called, and are destroyed on return from that function.

A declaration begins with the type, followed by the name of one or more variables. Syntax of declare statement is described as:

data_type  list_of_variables;

A list of variables includes one or many variable names separated by commas.

Single declarations

int age;         //integer variable 
float amountOfMoney;//float variable
char initial;// character variable

Multiple declarations:

int age, houseNumber, quantity; 
float distance, rateOfDiscount;
char firstInitial, secondInitial; 

Variables can also be initialized when they are declared, this is done by adding an equals sign and the required value after the declaration.

int high = 250;     //Maximum Temperature
int low = -40;      //Minimum Temperature 
int results[20];    //Series of temperature readings 


A constant is an object whose value cannot be changed. There are two method to define constant in C:

  • By #define statement. Syntax of that statement is:
#define  constant_name value
#define  MAX_SALARY_LEVEL  15 //An integer constant
#define  DEP_NAME  “Computer Science”
// A string constant
  • By using const keyword
const data_type  variable_name = value;
const double e = 2.71828182845905;

Functions printf, scanf

Usually i/o, input and output, form the most important part of any program. To do anything useful your program needs to be able to accept input data and report back your results. In C, the standard library (stdio.h) provides routines for input and output. The standard library has functions for i/o that handle input, output, and character and string manipulation. Standard input is usually means input using the keyboard. Standard output is usually means output onto the monitor.

  • Input by using the scanf() function
  • Output by using the printf() function

To use printf and scanf functions, it is required to declare the header <stdio.h>

The printf() function

The standard library function printf is used for formatted output. It makes the user input a string and an optional list of variables or strings to output. The variables and strings are output according to the specifications in the printf() function. Here is the general syntax of printf .

printf(“[string]”[,list of arguments]);

The list of arguments allow expressions, separated by commas.

The string is all-important because it specifies the type of each variable in the list and how you want it printed. The string is usually called the control string or the format string. The way that this works is that printf scans the string from left to right and prints on the screen any characters it encounters – except when it reaches a % character.

The % character is a signal that what follows it is a specification for how the next variable in the list of variables should be printed. printf uses this information to convert and format the value that was passed to the function by the variable and then moves on to process the rest of the control string and anymore variables it might specify.

For Example

printf("Hello World");

only has a control string and, as this contains no % characters it results in Hello World being displayed and doesn’t need to display any variable values. The specifier %d means convert the next value to a signed decimal integer and so:

printf("Total = %d",total);

will print Total = and then the value passed by total as a decimal integer.

The % Format Specifiers

The % specifiers that you can use are:

Usual variable type Display
%c char single character
%d (%i) int signed integer
%e (%E) float or double exponential format
%f float or double signed decimal
%g (%G) float or double use %f or %e as required
%o int unsigned octal value
%s array of char sequence of characters
%u int unsigned decimal
%x (%X) int unsigned hex value

Formatting Your Output

The type conversion specifier only does what you ask of it – it convert a given bit pattern into a sequence of characters that a human can read. If you want to format the characters then you need to know a little more about the printf function’s control string.

Each specifier can be preceded by a modifier which determines how the value will be printed. The most general modifier is of the form:

flag width.precision

The flag can be any of

flag meaning
left justify
+ always display sign
space display space if there is no sign
0 pad with leading zeros
# use alternate form of specifier

The width specifies the number of characters used in total to display the value and precision indicates the number of characters used after the decimal point.

For example,

%10.3f will display the float using ten characters with three digits after the decimal point. Notice that the ten characters includes the decimal point, and a – sign if there is one. If the value needs more space than the width specifies then the additional space is used – width specifies the smallest space that will be used to display the value.

%-10d will display an int left justified in a ten character space.

The specifier %+5d will display an int using the next five character locations and will add a + or – sign to the value.

Strings will be discussed later but for now remember: if you print a string using the %s specifier then all of the characters stored in the array up to the first null will be printed. If you use a width specifier then the string will be right justified within the space. If you include a precision specifier then only that number of characters will be printed.

For Example


will print Hello,

printf("%25s ,Hello")

will print 25 characters with Hello right justified

Also notice that it is fine to pass a constant value to printf as in printf(“%s,Hello”).

Finally there are the control codes:

\b backspace
\f formfeed
\n new line
\r carriage return
\t horizontal tab
\’ single quote
\0 null

If you include any of these in the control string then the corresponding ASCII control code is sent to the screen, or output device, which should produce the effect listed. In most cases you only need to remember \n for new line.

The scanf() function

The scanf function works in much the same way as the printf. That is it has the general form:

scanf(“control string”,variable,variable,...)

In this case the control string specifies how strings of characters, usually typed on the keyboard, should be converted into values and stored in the listed variables. However there are a number of important differences as well as similarities between scanf and printf.

The most obvious is that scanf has to change the values stored in the parts of computers memory that is associated with parameters (variables).

To understand this fully you will have to wait until we have covered functions in more detail. But, just for now, bare with us when we say to do this the scanf function has to have the addresses of the variables rather than just their values. This means that simple variables have to be passed with a preceding &.

The second difference is that the control string has some extra items to cope with the problems of reading data in. However, all of the conversion specifiers listed in connection with printf can be used with scanf.

The rule is that scanf processes the control string from left to right and each time it reaches a specifier it tries to interpret what has been typed as a value. If you input multiple values then these are assumed to be separated by white space – i.e. spaces, newline or tabs. This means you can type:

3 4 5





and it doesn’t matter how many spaces are included between items. For Example

scanf("%d %d",&i,&j);

will read in two integer values into i and j. The integer values can be typed on the same line or on different lines as long as there is at least one white space character between them.

The only exception to this rule is the %c specifier which always reads in the next character typed no matter what it is. You can also use a width modifier in scanf. In this case its effect is to limit the number of characters accepted to the width.

For Example


would use at most the first ten digits typed as the new value for i.

Here is an example to demonstrate the usage of printf and scanf functions

#include <conio.h>
#include <stdio.h>
void main()
// variable declaration
int a;
float x;
char ch;
char* str;
// Enter data
printf(“Input an integer”);
printf(“\n  Input a real number”);
printf(“\n Input a character”);
fflush(stdin); scanf(“%c”,&ch);
printf(“\n Input a string” );
fflush(stdin); scanf(“%s”,str);
// Output the data
printf(“\n Your data”);
printf(“\n Integer: %d”,a);
printf(“\n Float : %.2f”,x);
printf(“\n Char: %c:,ch);
printf(“\n String : %s”,str);

(Function fflush are used to avoid stopping the reading process when meet one or more spaces)

There is one main problem with scanf function which can make it unreliable in certain cases. The reason being is that scanf tends to ignore white spaces, i.e. the space character. If you require your input to contain spaces this can cause a problem.

Scanf will skip over white space such as blanks, tabs and new lines in the input stream. The exception is when trying to read single characters with the conversion specifiers %c. In this case, white space is read in. So, it is more difficult to use scanf for single characters. An alternate technique, using getchar, will be described later.

Other Input and Output Functions


The computer asks the user press a key. This key does not appear on screen. The syntax is:


getch() is used to terminate a program when the user press a key.


gets reads a line of input into a character array. The syntax is:



puts writes a line of output to standard output. The syntax is:

puts(name of string);

It terminates the line with a new line, ‘\n’. It will return EOF is an error occurred. It will return a positive number on success.

For using the statements mentioned above, you must declare the library <conio.h>.



C contains the following operator groups.

  • Arithmetic
  • Assignment
  • Logical/relational
  • Bitwise

Arithmetic Operators

The arithmetic operators are +, -, /, * and the modulus operator %. Integer division truncates any fractional part. The expression x%y produces the remainder when x is divided by y, and thus is zero when y divide x exactly.The % operator cannot be applied to a float or double.

The binary + and – operators have the same precedence, which is lower than the precedence of *, / and %, which is turn lower than unary + and – . Arithmetic operators associate left to right.

Operator Meaning Data type of the operands Examples
opposite integer, float
int a, b;
-12; -a; -25.6;
+ addition integer, float
float x, y;
5 + 8; a + x;
3.6 + 2.9;
subtraction integer, float
3 – 1.6; a – 5;
* multiplication integer, float
a * b; b * y;
2.6 * 1.7;
/ division integer, float
10.0/3.0;	(= 3.33…)
10/3.0; 	(= 3.33…)
10.0/3;       	(= 3.33…)
/ integer division integer
10/3;            (= 3)
% modulus integer
10%3;            (=1)

Assignment Operators

These all perform an arithmetic operation on the lvalue and assign the result to the lvalue. So what does this mean in English? Here is an Example

counter = counter + 1;

can be reduced to

counter += 1;

Here is the full set.

*= Multyply
/= Divide
%= Modulus
+= Add
-= Subtract
<<= Left Shift
>>= Right Shift
&= Bitwise AND
^= Bitwise Exclusive OR (XOR)
|= Bitwise Ixclusive OR

if expr1 and expr2 are expressions then

expr1 op= expr2 is equivalent to expr1 = expr1 op expr2

Logical and Relational Operators

Relational operators

Operators Meaning Examples
> greater than
2 > 3 (is 0)
6 > 4 (is 1)
a > b
>= greater than or equal to
6 >= 4 (is 1)
x >= a

< less than
5 < 3 (is 0), 
<= less than or equal to
5 <= 5 (is 1)
2 <= 9 (is 1)

== equal to
3 == 4 (is 0)
a == b
!= not equal to
5 != 6 (is 1)
6 != 6 (is 0) 

Logical operators

Operators Meaning Data types of the operands Examples
&& logical and 2 logic expressions
3<5 && 4<6 (is 1)
2<1 && 2<3 (is 0)
a > b && c < d
|| logical or 2 logic expressions
6 || 0 	        (is 1)
3<2 || 3<3	(is 1)
x >= a || x == 0
! logical not 1 logic expression
!3	(is 0)
!(2>5)	(is 1)

Bitwise Operators

Operators Meaning Data types of the operands Examples
& Binary AND 2 binary numbers
0 & 0    	(is 0)
0 & 1 	        (is 0)
1 & 0 	        (is 0)
1 & 1 	        (is 1)
101 & 110	(is 100)

| Binary OR 2 binary numbers
0 | 0 	        (is 0)
0 | 1 	        (is 0)
1 | 0 	        (is 0)
1 | 1 	        (is 1)
101 | 110	(is 111)

^ Binary XOR 2 binary numbers
0 ^ 0 	       (is 0)
0 ^1 	       (is 1)
1 ^ 0 	       (is 1)
1 ^ 1 	       (is 0)
101 ^ 110      (is 011)
<< Shift left 1 binary number
a << n     (is a*2n)
101 << 2   (is 10100)
>> Shift right 1 binary number
a >> n    (is a/2n)
101 >> 2  (is 1)

~ One’s complement 1 binary number
~ 0 		(is 1)
~ 1 		(is 0)
~ 110		(is 001)

Increment and Decrement Operators

Incrementing, decrementing and doing calculations on a variable is a very common programming task and C has quicker ways of writing the code. The code is rather cyptic in appearance.

The increment operator ++ adds 1 to its operand while the decrement operator – -subtract 1. We have frequently used ++ to increment variables, as in

if  (c = = ’\n’) 

The unusual aspect is that ++ and – – may be used either as prefix operators (before the variable, as in ++n) or postfix operators (after the variable, as in n++). In both cases, the effect is to increment n. But the expression ++n increments n before its value is used, while n++ increment n after its value has been used. This mean that in a context where the value is being used, not just the effect, ++n and n++ are different. For example, if n is 5, then

x = n++;

sets x to 5 but

x = ++n;

sets x to 6. In both cases, n becomes 6.

The increment and decrement operator can only be applied to variables; an expression like (i + j)++ is illegal.

Memory Addressing Operators

The five operators listed in the following table are used in addressing array elements and members of structures, and in using pointers to access objects and functions.

Operator Meaning Example Result
& Address of &x Pointer to x
* Indirection operator *p The object or function that p points to
[ ] Subscripting x[y] The element with the index y in the array x (or the element with the index x in the array y: the [ ] operator works either way)
. Structure or union member designator x.y The member named y in the structure or union x
-> Structure or union member designator by reference p->y The member named y in the structure or union that p points to

Type Conversions

When an operator has operands of different types, they are converted to a common type according to a small number of rules. In general, the only automatic conversion era those that convert a narrower operand into a wider one without loosing information, such as converting an integer into floating point .

If there are no unsigned operands, the following informal set of rules will suffice:

If either operand is long double, convert the other to long double.

Otherwise, if either operand is double, convert the other to double.

Otherwise if either operand is float, convert the other to float.

Otherwise convert char and short to int.

Then if either operand is long, convert the other to long.

A char is just a small integer, so chars may be freely used in arithmetic expressions

Precedence of Operators

Operators listed by type.

All operators on the same line have the same precedence. The first line has the highest precedence.

Level Operators Associativity
1 () [] . -> ++ (postfix) – (postfix) —–>
2 ! ~ ++ (prefix) — (prefix) – * & sizeof <—–
3 * / % —–>
4 + – —–>
5 << >> —–>
6 < <= > >= —–>
7 == != —–>
8 & —–>
9 ^ —–>
10 | —–>
11 && —–>
12 || —–>
13 ?: <—–
14 = += -= <—–

Note:associate left to right

How to Reuse & Attribute This Content
© Jul 29, 2009 Huong NguyenTextbook content produced by Huong Nguyen is licensed under a Creative Commons Attribution License 3.0 license.
Under this license, any user of this textbook or the textbook contents herein must provide proper attribution as follows:
The OpenStax name, OpenStax logo, OpenStax book covers, OpenStax CNX name, and OpenStax CNX logo are not subject to the creative commons license and may not be reproduced without the prior and express written consent of Rice University. For questions regarding this license, please contact support@openstax.org.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s