C Basics

(roughly chapter 2. read chapter 1 for an overview of C.)

A C program must always be in a text file whose name ends in .c. E.g.:

prog1.c
hello.c

Our first program is ~taw2/pub/hello.c.

Compiling C Programs

(pp 35 - 36)

A C compiler is a program that translates (or transforms) C programs into assembly or machine language programs that a computer can execute.

We'll be using a compiler called gcc. The dialect (version) of C we'll be using is called ANSI C ( American National Standards Institute C) or standard C. Many UNIX systems provide a compiler called cc, which compiles an older dialect of C, called Kernighan and Ritchie C (or K & R C) or traditional C.

To compile a program:

gcc filename

where filename is the name of the file containing the program. E.g.:

gcc hello.c
The resulting machine language (executable) program is placed in file a.out. To run the program, enter:
a.out
The name of the executable can be changed using the -o flag with gcc. E.g.
gcc hello.c -o hello
puts the executable in file hello.

Return to Table of Contents

General Structure of a C Program

/* preamble */
#include directives
#define directives

const declarations
variable declarations
function prototypes

/* main program */

main ()
{
  variable declarations
  body of main program (C code)
}

/* user defined functions */

Return to Table of Contents

Comments in C

Return to Table of Contents

Variable Declarations

In C, a variable must be declared before it can be used. The declaration tells the compiler to reserve some memory to store the value of the variable and established the type of the variable (e.g. int, float, char). Variable declarations can occur in the preamble, and after the { in main (preferred). The format of a variable declaration is:

typename variablename;

Legal variable names:

Every declaration ends with a semicolon.

int count; /* for counting sheep */
Commenting the purpose of a variable is often useful.

Multiple variables of the same type can be declared in one declaration. The variable names are comma separated.

int count1, count2;
Variables can be initialized (given an initial value) when they are declared.
int count1 = 3, count2 = 297;

Return to Table of Contents

Types for Variables

Numeric types in C.
type name description
int signed integers
float signed real numbers
double larger signed real numbers
signed real numbers with more decimal places
(used for scientific computing)
char single characters
(or integers from -128 to 127)

All numeric types can be preceded by short, long, signed or unsigned. Doing so affects how values of the type are stored and how they can be used.

Character constants are enclosed in single quotes. E.g.

 
char g = 'G';
Characters are represented as small integers, usually using the ASCII encoding scheme. (e.g. A is 65).

Return to Table of Contents

Assignment Statements

The value of a variable is changed by an assignment to that variable. In C, the assignment operator is =. Assignments (and all other statements) are ended by a semicolon.

#include <stdio.h>

main()
{
 int count1, count2;

 count1 = 297;
 count1 = 305; /* the previous value of 
                  count1 is lost */
 printf("The value of count1 is %d\n", count1);

 count2 = count1; /* now count2 and count1 have
                     the same value (305) */
 count2 = count2 + 3;
 /* result: count2 has value 308 */
}
On the right hand side of =, count2 refers to the value of the variable. On the left hand side of =, the variable count2 refers to a bit of memory to stick a value into.

Assignment for char, float and double is analogous to int assignment.

  char g;
  float f1, f2;

  g = 'G';
  g = 'l';
  f1 = 3.5182;
  f2 = f1 + 37.3;

Return to Table of Contents

Constants

literal constant
(or just literal) the actual string of characters making up some constant. E.g. 3.518, 'G', 3
symbolic constant
a named constant (like a variable whose value can't be changed with an assignment statement)

Literal constants by type.
type example literal description
char 'G' in single quotes
int (in decimal) 37
-25
as usual
int (in octal) 0670 starts with 0
int (in hexadecimal) 0x1AF6 starts with 0x
float
(and double)
3.518
-1.0
351.8e-2

can't end in .
= 351.8 * 0.01 = 3.518

Numeric literals never contain commas.

Symbolic constants are useful for commonly occurring constants, or constants that we might want to change systematically in a program.

The most common way to define a constant uses the #define directive:

#define PI 3.1415
Note that #define directives are NOT ended by ;

Once a constant is defined this way, it can be used anywhere in the program file.

A #define directive can also be used to define string constants.

#define HI "Hello World\n"
#define RESP "Enter Your Response: "
Note the use of double quotes vs. single quotes for characters.

Because C has no boolean type, it is often useful to define constants TRUE and FALSE.

#define TRUE 1
#define FALSE 0
Quiz: what's the value of (3 < 2) in C?

The second method of declaring a constant uses the keyword const and requires that the type of the constant be given.

const double PI = 3.1415;
Constant declarations of this form do end in ;

Return to Table of Contents

Arithmetic Operators and Expressions

signs:

 int x = 3;
 float f;
 int y;

 y = +x; /* now y = 3 */
 y = -x; /* now y = -1 * x 
                  = -3 */
 f = -37.23;

arithmetic expressions:

Arithmetic expressions using numeric variables x and y.
operation expression
addition x + y
subtraction x - y
multiplication x * y
division x / y
remainder
(modulo)
x % y

The type of the result of each of these expressions depends on the type of the arguments. The type of the result is the least type needed to contain that result. The order of the basic numeric types, from least to greatest, is:

int
float
double

Given the declarations:

  int i, j;
  float f;
  double d;
Example arithmetic expressions and result types.
expression result type
d + i double
d + f double
i + f float
i + j int
i * f - d double
i / j or j / i int
i / d or d / i double
i / f or f / i float
f / d or d / f double

Division by 0 will result in a run time error, as will using the remainder operator with a second argument of 0. If two int expressions are divided, and remainder is discarded. E.g.

5 / 4 == 1

The remainder operator (%) can only be applied to integer arguments (long and short ints are ok), and the result is an int. E.g.:

6 % 4 == 2 

Literal numeric constants that have no fractional part have type int. Those with a fractional part have type double.

These rules can be applied "bottom up" for more complex expressions. Given the previous declarations:

(i + f) / (f * 23.0)
has type double and
(3 / j) + f
has type float.

We need to know the result types of expressions because expressions are often used in assignment statements, and the type of the variable assigned to must be compatible with the type of the expression. E.g. given the previous declarations:

j = (i + f) / (f * d);
might:

Return to Table of Contents

Type Casting

The type of an expression can be changed using a type cast. Format:

(typename) expression

For example, given the previous declarations of i, j, f and d:

j = (int) ((i + f)/(f * d));
is safe, and truncates the value of the expression before assigning it to j.

Example:

d = (double) i/ (double) j;
forces double precision division of integers i and j.

Type casts have higher precedence than arithmetic operators, so use parentheses appropriately. (At the bottom of p. 30, the text states that the precedence of type casts is lower than that of arithmetic expressions. This is an error.)

Example:

d = (double) i/j;
is the same as:
d = ((double) i)/j;
so the type cast is done before the division, and d is assigned the double result including any fractional part.

Example:

d = (double) (i/j);
The integer division is done first, and then the integer result is cast to a double. Any fractional part is lost.

Return to Table of Contents

Precedence and Grouping

Arithmetic expressions are evaluated from left to right, except when the precedence of operators interferes.

Precedence of arithmetic operators, from highest to lowest
operatorprecedence
type casthighest
*, /, %
+, -
=lowest

Operators with higher precedence take their operands before operators with lower precedence.

Example:

(double) 3 + 4 * 5
is equivalent to
((double) 3) + 4 * 5
is equivalent to
((double) 3) + (4 * 5)
is equivalent to
((double) 3) + (20)
is equivalent to
23.0

Example:

i = 4 + 3 - 2/5 * 10;
is equivalent to
i = ((4 + 3) - ((2/5) * 10));
is equivalent to
i = 7 - 0;
is equivalent to
i = 7;

Use parentheses whenever you are in doubt.

Return to Table of Contents

Shortcut Operators

increment and decrement:

int count;

/* both of the following are
   equivalent to 

   count = count + 1 */

/* post increment */ 
count++;

/* pre increment */
++count;

/* both of the following are
   equivalent to 

   count = count - 1 */

/* post decrement */ 
count--;

/* pre decrement */ 
--count;

These operators can be used in expressions - on the right hand side of an assignment. The result depends on the pre/post distinction:

int result, count = 10;

result = count++;
/*  count = 11;
    result = 10; */

count = 10;
result = ++count;
/*  count = 11;
    result = 11; */

count = 10;
result = count--;
/*  count = 9;
    result = 10; */

count = 10;
result = --count;
/*  count = 9;
    result = 9; */
advice: don't use increments and decrements in expressions

other shorthands:

The following operators:

   +=
   -=
   *=
   /=
   %=
can all be used as shorthands when changing the value of a variable based on its previous value.

Example:

float f = 3.5;
int count = 10;

f += -29.7;
/* same as:

   f = f + -29.7;
*/

count %= 20;
/* same as:

count = count % 20;
and only works on integer types
*/

Return to Table of Contents

Using Electronic Mail

(pp. 318 - 319.)

You will be notified if you have new mail when you log in to a UNIX system. The mail program is standard on all UNIX systems and can be used to read and send email. To start the mail program, enter

mail
The mail program will display a numbered list of your mail messages. You can display a message by entering the number of the message you want to see. This also sets that message as the current message.

Mail commands: (at the & prompt)
command meaning
? help
h display message list with the current message marked with a >
Enter display current message
d delete current message
d n delete message number n
n display message number n and make it the current message
s filename save current message to file filename
r send a reply to the current message (automatically goes to whoever sent the message)
r n reply to message number n
m userid@address send email to user userid of system address
q quit mail and remove deleted messages
x quit mail but don't remove deleted messages

Any messages you have read but not deleted will be stored in the file mbox. To see them again, start the mail program with the -f flag:

mail -f mbox

Sending mail

You can send mail to another user on the same system without specifying an address. E.g.:

m taw2
from inside the mail program on farman will send email to me on farman. To send email to a user of another system, you must specify the name of that system as their address. E.g:
m wahls@psu.edu
Using the r command inside mail automatically supplies the correct user id and address for responses to email messages. You can also send a single message without starting the mail program first. E.g., enter:
mail wahls@psu.edu
at the UNIX prompt.

When you start sending mail, you will be prompted for a subject (an optional, brief description of the message). Enter a subject if you like, then press Enter.

Next enter your message. There is no prompt and no editor is used, so you can't fix mistakes on previous lines. When you are finished composing your message, either enter control-D or put a period as the first character on a line by itself. To abort the message (not send it), enter control-C twice.

You can email the contents of a file as follows:

mail userid@address < filename

To give a subject when sending a file:

mail -s 'subject' userid@address < filename

The subject line must be in single quotes, and the -s flag must immediately follow the mail command. (Mistake in the text.)

The from command displays a list of your current messages without starting the mail program.

Many UNIX systems have a more user-friendly email handler installed. Examples: elm, pine, mh and Sun's mailtool. Some of the features of elm are:

If you have multiple accounts on different systems (and so multiple email addresses), you can forward all of your email to one place. On a UNIX system, this is done by creating a file named .forward in your home directory. This file contains the email address you want your email forwarded to.

Return to Table of Contents