C Language Overview
Why C?
- System level programming! Operating systems, network protocols, device drivers (printer, keyboard, etc)
- Very fast and efficient memory usage
- The dark side: obscure code, easy to create security vulnerabilities, easy to shoot yourself in the foot
- The burden is on the programmer to get things right; C won't protect you from yourself
C compilers
- Different language versions evolved over time
- Compilers these days are "retargetable", a single compiler can compile to many different machine architectures
- Our official C compiler is
gcc
REFERENCE: Skim through this C tutorial to start.
The Programming Process
- Store source code in
file.c
- Create source code with editor (
pico
,emacs
,vi
, etc.) - Compile & run
-
gcc file.c
createsa.out
file; run with./a.out
command -
gcc -o file file.c
creates executable namedfile
; run with./file
command
-
The compilation steps for C
- Pre-processing:
#include
files, definitions - Compile (program =
.c
/.h
files = source code; assembly; machine = object code =.o
file) - Link w/library routines
- Load into memory
- Execute = run in CPU
Preprocessor directives
-
#include "header.h"
-- in effect insert the fileheader.h
contents here -
#define THING value
-THING
is a macro abreviation forvalue
Code comments
- Block comment:
/* here is a
long comment */ - Short (to end of line) comment:
// here is my comment
Testing
Assertions are particularly useful in functions to check the validity of parameter values. When an assertion fails, the program will stop running. If it passes (results in true), then the program keeps going.
-
#include <assert.h>
-
assert(boolean expr);
C Data Types
Primitive data types
-
char
,short
(int),int
(default),long
(int),float
,double
(-sized float),long double
(quadruple-sized float) -
unsigned
qualifier can apply to any to restrict to non-negative -
const
qualifier to make the data immutable (same asfinal
in Java) - C is not as strongly typed as Java, e.g. array access out of bounds is not a checked exception (though it will often crash your program anyway; this is usually the cause of a
segmentation fault
). - Exact sizes of each type are platform dependent;
int
is generally 32-bit except on 16-bit processors.
WARNING: In C, variables are not initialized for you; they contain junk (prior bit values in memory) and may produce erratic results!!
Integer constants
- Decimals (base 10):
int
:13
,23
,-14
, etc.
long
(integer):13L
,-14l
, etc. - Octal (base 8) - precede value with 0
digits range from 0 to 7
032
- Hexadecimal (base 16) - precede value with
0x
digits range from 0 to 9 and a-f or A-F
0x15
,0xA
- Binary (base 2) - precede value with
0b
digits are 0 and 1 only
0b1000
,0b01101
Booleans
-
bool
type added in c99 w/valuestrue
,false
- In older (most) C code you will see
int
s, where 0=false, non-zero=true used instead - In C, any integer type may be used as a boolean; a value of
0
is treated asfalse
, and any other value is treated astrue
.
ASCII characters, escape sequences
-
#include <ctype.h>
if you want to use character library functions; Reference forctype.h
functions -
isalpha('a')
(returnstrue
),isdigit
, etc. functions to test characters -
tolower('A')
,toupper('a')
for case conversion - Note the previous functions have return type
int
, notchar
-- this is because return value-1
is used to indicate error.
Size calculations
sizeof
operator: returns integer # bytes of object-
sizeof(anytype)
,sizeof varname
Type Casting
- Convert one type of data to another
- For types int/float/double/char/etc will convert layout format
- For other types may just re-interpret the bits as the new type
- Casts in C never fail at runtime (unlike Java)
- [Implicit] Casts in C can do bad things!
#include <stdio.h>
int main() {
// example of up-cast for an explicit conversion
int i = 45;
// turn an int (4-byte) into a double (8-byte)
double j = (double) i; // "(double)" here NOT necessary, compiler will convert
printf("float %f\n", j);
// useful up-cast conversion for floating division
int n1 = 4, n2 = 16;
printf("floating point division result %f\n", (float) n1 / n2);
char c = i; // implicit down-cast conversion, 4-byte to 1-byte (drop 3 bytes)
printf("character %c\n",c);
long int l = 23983982;
int *ptr = (int *) l; // ptr points to memory location 23983982 - a BAD idea!
// i = *ptr; // uncomment and get a core dump
// casting between pointers and integers sometimes useful however
short int a[] = {1,2};
short int *ptr0 = a; // start of array
short int *ptr1 = a+1; // 2nd element
printf("size of short int is %ld bytes\n",(long int) ptr1 - (long int) ptr0);
return 0;
}
C Operators
Common Operators
- Arithmetic:
+ - * / %
(no exponentiation operator) - Relational:
< > <= >= == !=
- Logical:
!
not&&
and||
or - Assignment:
= += -= *= %= ++ --
- Precedence order: always know where to look this up quickly (e.g. here)
- Short-circuit (lazy) evaluation of boolean expressions
WARNING on equality and assignment:
if (num = 10) // evaluates to 10, which is considered to be true (non-zero)
if (num == 10) // double equals only evalutes to true if num is in fact a 10
Bitwise operators
-
num1 & num2
- bitwise and -
num1 | num2
- bitwise inclusive or -
num1 ^ num2
- bitwise exclusive or -
~num1
- bitwise complement -
num << shiftbits
- left shift of num by shiftbits places, pad 0 right -
num >> shiftbits
- similar right shift, pad is system dependent
Built-in floating-point math functions
- Use
#include <math.h>
- Need to compile with
gcc -lm
option - Math library functions generally take
double
arguments, returndouble
values - eg:
sqrt(x)
,pow(x,y)
,exp(x)
,log(x)
,ceil(x)
,floor(x)
,sin(x)