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.
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.cThe resulting machine language (executable) program is placed in file a.out. To run the program, enter:
a.outThe name of the executable can be changed using the -o flag with gcc. E.g.
gcc hello.c -o helloputs the executable in file hello.
/* 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 */
/* /* */ */is illegal
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;
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).
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;
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.1415Note 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 0Quiz: 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 ;
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:
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;
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) + fhas 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:
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.
Arithmetic expressions are evaluated from left to right, except when the precedence of operators interferes.
operator | precedence |
---|---|
type cast | highest |
*, /, % | |
+, - | |
= | lowest |
Operators with higher precedence take their operands before operators with lower precedence.
Example:
(double) 3 + 4 * 5is equivalent to
((double) 3) + 4 * 5is 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.
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 */
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
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
You can send mail to another user on the same system without specifying an address. E.g.:
m taw2from 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.eduUsing 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.eduat 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.