Let's take a look at a simple C program, test.c without any real code:
#include <stdio.h>
int main ()
{
}
NOTE:
- We can compile this content-free program
gcc -o test test.c
and execute it:
test
- Since #include <stdio.h> appears in every
program, we will omit including it in our sample code snippets shown below.
Next, let us add some comments:
// Comment 1
int main () // Comment 2
{
// Comment 3
}
// Comment 4
NOTE:
- There are three comments in the file.
- Each comment begins with the reserved symbol // (two forward slashes).
- All text from after the comment symbol to the end of the line
is ignored by the compiler.
- Note that // comments were added to C only in the ANSI
C99 standard. Thus, prior to 1999, we would have to write the same
program as:
/* Comment 1 */
int main () /* Comment 2 */
{
/* Comment 3 */
}
/* Comment 4 */
- You can force compilation to pre-99 C by the use of an
appropriate compiler option, e.g.,
gcc -std=c89 -o test test.c
For the remainder we will assume C99.
Next, let's play around with the program to highlight a few syntax
issues:
- Whitespace between keywords, symbols and identifiers is
compressed:
- Example:
// Comment 1
int main ( ) // Comment 2
{
// Comment 3
}
// Comment 4
- Example:
// Comment 1
int
main (
)
// Comment 2
{
// Comment 3
}
// Comment 4
- Whitespace in comments is not processed by the compiler.
In-Class Exercise 0.1
The following program will not compile. Why? And what kind of error is
identified by the compiler?
// Comment 1
int main () // Comment 2
{
//
Comment 3
}
// Comment 4
In-Class Exercise 0.2
Is a comment allowed between parameter brackets?
// Comment 1
int main ( // Comment 2
)
{
// Comment 3
}
// Comment 4
C programs are case-sensitive. The following program
will not compile:
Int main ()
{
}
This is because the C reserved word int is mis-spelt as
Int.
Notice that the error produced above by the (gcc)compiler is simply:
test.c:3: parse error before 'main'
Thus, the compiler does not know you mis-typed.
In-Class Exercise 0.3
What is the error produced by compiling this program?
int Main ()
{
}
In-Class Exercise 0.4
What is the error produced by compiling this program?
int main ()
{
Printf ("Hello World!\n");
}
HelloWorld
Consider the classic helloworld program in C:
int main ()
{
printf ("Hello World!\n");
}
The main syntactic elements are:
- C's only reserved word in this program: int.
- Function names: main, printf.
- Delimiters for the function main.
- An end-of-statement symbol, the semicolon.
- Parentheses for enclosing method parameters (arguments).
- A string literal, Hello World!.
- Braces that delimit the body of main.
Next, let us get accustomed to errors produced by the compiler
when the syntax is incorrect.
In-Class Exercise 0.5
What errors are reported by the compiler with this program?
int main ( // Forgot the matching right parenthesis
{
printf ("Hello World!\n");
}
In-Class Exercise 0.7
What errors are reported by the compiler with this program?
int main ()
{
printf ("Hello World!\n); // Forgot the matching right quote (")
}
In-Class Exercise 0.8
What errors are reported by the compiler with this program?
int main ()
{
printf ("Hello World!\n") // Forgot the semi-colon.
}
In-Class Exercise 0.9
What errors are reported the compiler with this program?
int main ()
{
printf ("Hello World!\n");
// Missing brace
In-Class Exercise 0.10
Try to compile and run this program.
main ()
{
printf ("Hello World!\n");
}
Data types and Identifiers
Let us examine some code with only int's to get started:
int main ()
{
// Declare an integer variable called "i".
int i;
// Assign it a value. Note the assignment operator "="
i = 5;
// Print out its value to the screen.
printf ("%d\n", i);
}
Next, let's play around with the syntax and observe what the
compiler reports.
In-Class Exercise 0.11
Try to compile and run this program.
int main ()
{
// Didn't declare "i"
// Assign it a value. Note the assignment operator "="
i = 5;
// Print out its value to the screen.
printf ("%d\n", i);
}
In-Class Exercise 0.12
Try to compile and run this program.
int main ()
{
// Declare an integer variable called "i".
int i;
// Wrong assignment operator
i := 5;
// Print out its value to the screen.
printf ("%d\n", i);
}
NOTE:
- Good programming style requires that variable names be chosen
for readability.
- Variable names like i are usually only appropriate
for loop (control) variables.
- What kinds of variable names are allowed?
The rules that apply to variable names also apply to
method and parameter names, the so-called identifiers.
About identifiers:
- An identifier must begin with a letter or underscore
- An identifiers can contain any number of letters, digits, or underscores.
- Case (upper or lower) is significant.
- No C reserved word can be used as an identifier.
- Examples of legal identifiers:
i
really_important_integer_for_counting_lines_in_a_text_file (bad style)
num_lines_in_file (acceptable, old C style)
numLinesInFile (recommended, new C style)
More about variable declaration syntax:
- Variables can be assigned values in a declaration:
int main ()
{
// Declare an integer variable called "i" and assign it a value.
int i = 5;
// Print out its value to the screen.
printf ("%d\n", i);
}
- Declarations can occur anywhere in a program body in C99 but
not in earlier versions.
- Multiple variables (of the same type) can be declared in a
single statement:
int main ()
{
// Declare multiple variables of the same type.
int i = 5, j = 6, k;
k = 7;
printf ("i=%d j=%d k=%d\n", i, j, k);
}
The preferred style is either:
int main ()
{
int i = 5; // i is the variable that ....
int j = 6; // j ...
int k = 7; // k ...
printf ("i=%d j=%d k=%d\n", i, j, k);
}
or
int main ()
{
int
i = 5, // i is the variable that ....
j = 6, // j ...
k = 7; // k ...
printf ("i=%d j=%d k=%d\n", i, j, k);
}
More Data Types
While there are seven additional data types, we will first focus on
a few:
- double
- Use double to store floating point numbers, as in:
int main ()
{
double
pi = 3.14159, // The constant Pi
radius = 2.0E03, // Circle radius in exponent format.
area = 0; // Area, not yet computed.
area = pi * radius * radius;
printf ("Area of circle with radius %lf is %lf\n", radius, area);
}
- double constants are decimal values
(3.14159), or in exponent notation (2.0E03).
- char
- A char variable holds a single character, e.g.,
int main ()
{
char
initial1 = 'J',
initial2 = 'F',
initial3 = 'K';
printf ("Initials: %c %c %c\n", initial1, initial2, initial3);
}
- "Backslash" combinations are used to represent special characters:
int main ()
{
char initial1 = 'J';
char initial2 = 'F';
char initial3 = 'K';
char newline = '\n';
char tab = '\t';
printf ("%c Initials: %c \" %c %c %c \" %c", newline, tab, initial1, initial2, initial3, newline);
}
- Notice the double quote character inside the string
"Initials: %c \".
- Strings
- Strings in C are really char-arrays, pointed to by a variable
of type char *
- Example:
int main ()
{
char *str1 = "Hello";
char *str2 = "World!";
// String constants can be concatenated by whitepace:
char *str3 = "Hello" " again";
printf ("%s %s \n %s \n", str1, str2, str3);
}
Casting
Casting is the term used to convert a value of one data type to
a value of another data type. For example:
int main ()
{
int i = 5, j = 6;
double x = 2.718, y = 3.141;
// Implicit cast:
x = i;
printf ("x = %lf\n", x); // Prints 5.0
// Explicit cast:
j = (int) y;
printf ("j = %d\n", j); // Prints 3
}
In-Class Exercise 0.13
What does the following program print out?
int main ()
{
printf ("%lf\n", ( (double) (int) 3.141 ) );
}
Expressions
Arithmetic expressions:
In-Class Exercise 0.14
What does the following program print out?
int main ()
{
int k = 13;
int i;
for (i=0; i < 8; i++) {
printf ("%d ", (k % 2));
k >>= 1;
}
printf ("%\n");
}
Boolean expressions:
- Boolean operators include:
| && | AND |
| || | OR |
| ! | NOT |
| & | Bitwise AND |
| | | Bitwise OR |
| ^ | Bitwise XOR |
- Examples of boolean expressions used in if statements:
if (i == 10)
printf ("i is equal to 10");
if ( !(i == 10) )
printf ("i is not equal to 10");
if (i < 10)
print ("i is less than 10");
if ( (i >= 5) && (i <= 10) )
print ("i is between 5 and 10");
if ( (i >= 5) && (i != 6) )
printf ("i larger than 6");
Statements
Finally, we will examine some basic Java statements.
The following is not meant to be exhaustive, but rather, a quick
introduction to the most commonly used statements:
- Assignment:
- Assignment statements use the assignment operator =,
e.g.,
x = 5; // Simple assignment.
y = getInputValue(); // Assign a function's return value.
z = (x + y) / y; // Assign an expression value.
- Assignment can be combined with many operators, e.g.,
x += 5; // Add 5 to x
- Assignments can be grouped:
x = y = z = 0; // All are given the value 0.
- if-statement:
- An if-statement is the keyword if followed by a
boolean expression in parentheses, followed by a statement.
- Example:
if (x < 5)
printf ("x is less than 5");
- compound-statement:
- Compound statements are groups of statements placed in a
single block.
- A block is delineated with braces.
- Example:
if (x < 5) { // Start of block
y = 5;
z += x;
} // End of block
- Example:
if (x < 5) { // Start of outer block
y = 5;
z += x;
if (z > 10) { // Start of inner block
z = z - 1;
w = z * z;
} // End of inner block
} // End of outer block
- if-else and if-else-if statements:
- Example of if-else
if (x < 5) {
printf ("x is less than 5");
}
else {
printf ("x is not less than 5");
}
- Example of if-else-if
if (x < 5) {
printf ("x is less than 5");
}
else if (x > 5) {
printf ("x is greater than 5");
}
else if (x == 5) {
printf ("x is equal to 5");
}
else {
// Logically impossible!
}
- while loop:
- Example:
printf ("Countdown: ");
i = 10;
while (i >= 1) { // Start of while-body
printf ("%d\n", i);
i--;
} // End of while-body
- Any boolean expression can be used for the while-test
expression (i.e., in place of i >= 1).
- for loop:
- Example:
int i;
printf ("Countdown: \n");
for (i=10; i >= 1; i--) { // Start of for-body
printf ("%d\n", i);
} // End of while-body
- The loop-header first has a statement (int i = 10)
then a boolean expression (i>=1), followed by another
statement (i--), each separated by a semi-colon.
- Note: for consistency with C versions prior to C99, the
for-loop variable is defined earlier.
- Each statement (first, and third parts) can consist of
multiple comma-separated statements:
int i, j;
printf ("Weird countdown/up: \n");
for (i=10, j=1; ( (i >= 1) && (j <= 10) ); i--, j++) {
printf ("i=%d j=%d\n", i, j);
}
- Sometimes, the flexibility offered by the for-loop can be
taken too far, making some code examples difficult to read:
printf ("Really weird countdown/up: \n");
for (countInitializer (i,10), countInitializer (j,1);
checkCountGreaterEqual (i, 1) && checkCountLessEqual (j, 10);
incrementCount (i, -1), incrementCount (j, 1)) {
printf ("i=%d j=%d\n", i, j);
}
In-Class Exercise 0.15
What's wrong with the statement below? What happens when you compile?
if (i = 5)
printf ("i is equal to 5");
In-Class Exercise 0.16
What is the error in the following code?
int i = 10;
while (i >= 1)
printf ("i=%d\n", i);
i--;
Functions
Other languages call them "procedures" or "methods". C calls
them functions:
- A function refers to both a procedure (doesn't return a
value) or a function (does return a value).
- A function that does not return a value returns a void
value.
- A function declaration has a
return type, followed by the name, followed by parameter declarations.
- Example of a simple (static) method declaration:
void printHello ()
{
printf ("Hello World!");
}
int main ()
{
printHello ();
}
Note:
- The method printHello() has no parameters.
- The return type is void.
- Although main doesn't return anything, it's return
type is declared as int, for the esoteric applications
in which the int is used.
- Example with parameters and return values:
int squareIt (int inputInteger)
{
int squareValue = inputInteger * inputInteger;
return squareValue;
}
int main ()
{
int i = 5;
int j = squareIt (i);
printf ("The square of %d is %d\n", i, j);
}
Note:
- The method squareIt() takes one int parameter and
returns an int.
- The return-statement is the keyword return followed
by an expression whose type is the same as the return type.
- Let's consider some variations of the previous example to
illustrate a few points:
- The return-expression can be of any type that can be cast into
the return type, e.g,
int squareIt (int inputInteger)
{
double squareValue = inputInteger * inputInteger;
return (int) squareValue; // Cast to return type
}
int main ()
{
int i = 5;
int j = squareIt (i);
printf ("The square of %d is %d\n", i, j);
}
-
We can "tighten" the code in two ways:
int squareIt (int inputInteger)
{
return (inputInteger * inputInteger);
}
int main ()
{
int i = 5;
printf ("The square of %d is %d\n", i, squareIt (i));
}
In-Class Exercise 0.17
What happens if the function squareIt follows main?
int main ()
{
int i = 5;
printf ("The square of %d is %d\n", i, squareIt (i));
}
int squareIt (int inputInteger)
{
return (inputInteger * inputInteger);
}
In-Class Exercise 0.18
Is it possible for a function to return a value, but that the
value not be used?
int squareIt (int inputInteger)
{
return (inputInteger * inputInteger);
}
int main ()
{
int i = 5;
squareIt (i); // Return value not used.
}