Data types, basic arithmetic

From Programming In C

Table of contents

Data Types

We saw in Session 1 that variables have a data type associated with them. This makes the variable known to the compiler and tells the compiler how to store values assigned to that particular variable in computer memory. The most common types that you will be using are integer variables, real variables and character variables, these are represented by the C types int, float and char respectively, these and other data types are discussed below.

Integers (data type int)

are the preferred data type for any variable that is known to 'never' have a floating point or decimal part. On most machines, 32 bits (4 bytes) are assigned to each standard length integer variable, this allows a range of numbers from -231 to 231-1 or -2,147,483,648 to 2,147,483,647 to be represented;

Floating point numbers (data type float)

may contain a decimal part. As such they are stored in a completely different way on the computer but again 32 bits or 4 bytes of computer memory is typically assigned to each variable. The representation and range of floating point numbers varies from computer to computer, further details can be found in the further reading on this topic;

Character variables (data type char)

represent single characters where characters are stored as special (so-called ASCII) codes. String handling is possible using arrays of characters, this will be discussed again in Topic 7;

Double precision floating point numbers (data type double)

generally use twice as many bits as float in computer memory to store the number (i.e. usually 8 bytes rather than 4 bytes), thus increasing the accuracy with which the number can be represented and the range of valid numbers;

Constant variables (const keyword)

the const keyword prefixes a standard data type in a variable declaration and forces that variable to then remain constant. Constant variables must be initialised at the same time as they are declared. The variable name is known as the 'named constant' or 'constant' and the actual value that it is initialised to is known as the 'literal value' or 'constant value'. Using named constants is good programming practise as it means a frequently used constant value only has to be initialised once in a program. It also ensures that a variable that should remain fixed throughout the program isn't changed at all. For example:

 double miles, kms;
 const double miles2km=1.609; // conversion factor miles to km
 // some code here
 printf("Number of km travelled %f\n",miles*miles2km);

Other data types or modifiers to these data types exist such as short, long, unsigned (increases range if no negative numbers need to be represented), etc., none of which are used in this course. More details can be found in the further reading on this topic.

Arithmetic and operators

Once a variable has been assigned (via a declaration or assignment statement) it is then possible to use that variable in various arithmetic and other operations. This is done via 'operators' which act on one or more 'operands'. Binary operators act on two operands and unary operators act on one operand. The standard arithmetic actions 'add', 'subtract', 'multiply' and 'divide' are represented by the characters +, -, * and / respectively. Arithmetic is done via assignment statements, simple examples of which are given below:

 float opposite=2.6;
 float adjacent=3.4;
 float hypoth_sq=opposite*opposite+adjacent*adjacent;

Operator precedence and associativity

As expressions get more complicated we need to know the order in which the operators in the expression will be processed, this is known as operator precedence. Consider, for example, the assignment

 int rotate = 3 + 3 * 4 + 4;

Here there are 3 possibilities:

  1. If + has precedence over * then rotate will be initialised to a value of 48;
  2. If * has precedence over + then rotate will be initialised to a value of 19;
  3. If both *and + have equal precedence then rotate will be initialised to a value of 28;

In C the * and / operators have precedence over + and -.

Operators with equal precedence are evaluated according to their associativity. In general, operators with equal precedence will have left-right associativity which means that all the * and / operators in an assignment statement are treated reading the statement from left to right. This is also true for the + and - operators. It is good practise to use parentheses in complicated arithmetic assignments.

Commonly used operators

The table below lists commonly used operators, some of which are binary, some of which are unary.

Operator Meaning Usage
+ Addition of both operands y=a+b;
- Subtract 2nd operand from 1st y = a-b;
* Multiplication of both operands y=a*b;
/ Division of 1st operand by 2nd y=a/b
% Modulo of 1st operand w.r.t. 2nd
use with integers only
i = j%k;
++x Increment x by 1 and then assign y = ++x;
x++ Assign and then increment by 1 y=x++;
--x Decrement x by 1 and then assign y =--x;
x-- Assign and then decrement by 1 y=x--;
+= Assign left operand to left plus right operands x+=y;
same as
x=x+y;
-= As above for subtraction x-=y;
same as
x=x-y;
*= As above for multiplication x*=y;
same as
x=x*y;
/= As above for division x/=y;
same as
x=x/y;
%= As above for modulus x%=y;
same as
x=x%y;

Note that in integer division the non-integer part of the result is thrown away (i.e. the number is always rounded down) and so, for example

 int i=20;
 int j=3;
 int k=i/j;
 printf("k is %d",k);

will print the result

 k is 6

Note, it is important to understand the difference between, e.g. x++ and ++x, this is best illustrated via the following code fragment:

 int x,y,z;
 x = 1;
 y = x++;
 z = ++x;
 printf(" x is %d y is %d z is %d\n",x,y,z);
 x = 1;
 y = ++x;
 z = x++;
 printf(" x is %d y is %d z is %d\n",x,y,z);

which will print the result

 x is 3 y is 1 z is 3 
 x is 3 y is 2 z is 2

Conversion, casting

A reasonable question to ask is what happens to an arithmetic expression which involves a mixture of int, float and double. In general there is a complicated set of rules covering all variable types, full details of which can be found in the further reading on this topic. In this course we will concentrate on numerical variables of types int, float and double only in which case the rules are simpler:

  • If an expression involves a mixture of variables types one of which is double then all are considered as double when the expression is evaluated
  • Otherwise, if an expression involves a mixture of variables types one of which is float then all are considered as float when the expression is evaluated

It is possible to force a variable of one type to be treated as that of another type by prefixing the variable with (variable_type), this is known as casting. A useful example of this is given below which shows how to take the integer part of a float or double (bear this is mind for the Exercises!).

 int i;
 float a;
 a=2.3;
 i = (int) a;

Commonly used mathematical functions

The most commonly functions are

Name Meaning Usage
sqrt() square root y=sqrt(x);
sin() sine y=sin(x);
cos() cosine y=cos(x);
tan() tangent y=tan(x);
asin() arcsine y=asin(x)
(y in rads)
acos() arccosine y=acos(x)
(y in rads)
atan() arctangent
(tan-1(x))
y=atan(x)
(-π/2 < y < π/2)
atan2() arctangent
(tan-1(x1/x2))
y=atan2(x1,x2)
(-π < y < π)
abs() absolute value
returns integer
i=abs(x);
fabs() absolute value y=fabs(x);
pow() xy z = pow(x,y);
exp() ex y=exp(x);

Note that if your C program uses any of these functions you should add the line

 #include<math.h>

at the top of your code.

Basic input/output

This section deals with interacting with the computer program. Even with arithmetic you can't do very much other than write programs that are the equivalent of a pocket calculator. The real break through comes when you can read values into variables as the program runs. Notice the important words here: as the program runs. In order to communicate with the program as it runs we need to use commands that cause data to be input into the program and data to be output to the screen from the program. This is referred to as input/output or I/O for short.

Output: the printf statement

We have now seen two slightly different uses of the printf statement. This is a powerful and much used command. The printf command has the following general form:

 printf (some_string,value1,value2,...);

The first parameter of the command is always a string. The other parameters are optional and they depend on the string parameter. The ellipsis (...) means that the function can take as many parameters as the user requires. The string specifies how many of these parameters are needed. The function scans the string looking for something we call conversion specifiers. These can be thought of as placeholders where the value of a variable will be put when the string is written out. Conversion specifiers begin with a percent symbol, %, which is followed by a single letter that specifies what type of data is to be output. In Topic 1 we used %d to specify that an integer was to be printed on the screen. Once the specifier has been found in the string the command then substitutes in the corresponding value from the parameter list.

The printf conversion specifiers are:

Conversion character How argument is printed
c As a character
d As an integer
e as a floating point number (scientific notation)
f as a floating point number
g in the e-format or f-format, whichever is shorter
s as a string

An example of how the printf statement can be used is given below

 int a,b;
 float c;
  
 // some code here that calculates a,b and c
  
 printf("The value of a is %d, the value of b is %d, the value of c is %f\n",a,b,c);

Recall that the \n causes a linefeed to take place.

An optional number can be placed after the % sign in the conversion specifier, this determines how many spaces or columns the variable will occupy when it is printed out.

Input: the scanf statement

The scanf statement works is analogous to the printf statement but is used to input information from the terminal (your keyboard) to the C program as it runs. Syntactically, the scanf statement has the same form as the printf statement, i.e. the first field is a string containing conversion specifiers, followed by one or more variable names which are the variables to be read in. The main difference compared with the printf statement is that the variable names are each prefixed with a &. (In fact, what is being used here is a pointer to the variable but we won't come across pointers until Topic 6. The list of conversion specifiers looks almost identical to that used for the printf statement with the exception of the distinction between float and double:

Conversion character Type of variable expected
c character
d integer
f as a floating point number (float)
lf floating point number (double)
LF floating point number (long double)
s string

Often scanf and printf are used together when prompting for information to be entered at the keyboard as in the example below:

 int x;
 printf("Enter the value for x :");  // Note: no "\n" here
 scanf("%d",&x);

Note that the only exception to the rule concerning & is when reading in a string (as defined as an array of characters), in this case no & is used in front of the string name.

If you wish to read more than one variable in from the terminal (your keyboard) you can use a single scanf statement, for example:

 int x;
 double y;
 printf("Enter values for x (integer) and y (real) :");
 scanf("%d %lf",&x,&y);

As seen above, it is possible to add to the list of variables to be read in via this single scanf statement, a comma must be used to separate each new variable to be read in.

In the above scanf statement the space between the input conversion characters %d %lf isn't necessary. It is however good practise to leave a space between input conversion characters. This becomes more important when reading input from files as will be covered in Topic 6. It isn't necessary to enter x and y on the same line, for example, you can enter a value for x then hit return before entering the value for y. scanf will simply wait until it has got all the information it needs.

Preprocessor Directives

Finally a word about those lines that you find at the start of any C program that start with a "#" (usually referred to as a hash or pound symbol). These lines of code are not processed by the compiler itself but by the so-called pre-processor step that runs before the compiler. There are many types of pre-processing directives, the two you are most likely to encounter during this course are:

#include<filename.h> 
this effectively does a "cut and paste" of the file filename.h at that point in the program. Usually, the files to be included are system files containing definitions for system commands such as printf etc., or definitions for in-built functions such as sqrt,sin, etc.
#define VARNAME value 
sets up a constant value for the duration of the program. For example,
#define PI 3.14159
would cause a "cut and paste" of every occurrence of PI in the program with the value 3.14159.

Note: usually all preprocessor directives are placed at the beginning of the C program.

Further Reading

A Book on C Kelley and Pohl

  • pages 107-121 (data types),
  • pages 81-91 (operators and associativity),
  • pages 127-130 (mathematical operators),
  • pages 131-134 (conversion and casting),
  • pages 18-21 (basic I/O),
  • pages 91-96 (preprocessor)

Return to the course summary

phy225: Course Details

general


compilers


2011-12 assessments


past exam papers

  • 2008-9 (http://physics-database.group.shef.ac.uk/exampapers/2008-09/PHY225%20LT.pdf)
  • 2009-10 (http://physics-database.group.shef.ac.uk/exampapers/2009-10/PHY225%20Exam%20Sem%201%202009-10.pdf)
  • 2010-11 (http://physics-database.group.shef.ac.uk/exampapers/2010-11/PHY225_10_11.pdf)