Chapter 0 C Programming The C Language We are programming in C a subset of C C was originally compiled into C No classes templates namespaces userdefined overloading streams Here is a good reference to the language and the basic C libraries ID: 408370
Download Presentation The PPT/PDF document "CSCI 3431: Operating Systems" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
CSCI 3431: Operating Systems
Chapter 0 – C ProgrammingSlide2
The C Language
We are programming in C, a subset of C++
C++ was originally compiled into C
No classes, templates, namespaces, user-defined overloading, streams
Here is a good reference to the language and the basic C libraries:
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/Slide3
C's Foundations
C is really just a structured version of assembly language
Very minimal library support
Meant for systems programming – originally created as a language to program Unix
Created by Brian Kernighan and Dennis Ritchie at Bell Labs
Developed before mice, GUI's
A reference manual (online or paper) is essential Slide4Slide5
The File Model
All C I/o is done using files
3 special files are provided:
stdin
,
stdout
, and
stderr
These files are automatically opened and closed for you by the compiler
I/0 can be done directly using
fread
()
and
fwrite
()
More useful to do formatted I/o using
fprintf
()
and
fscanf
()Slide6
Formatted Output
fprintf
(file, “format”, values);
Various version of
fprintf
()
exist:
printf
(...)
is the same as
fprintf
(
stdout
,...)
sprintf
()
: print to a string (or character buffer)
v_printf
()
: variable number or
args
Other output functions are also available:
fputc
()
,
putc
()
,
putchar
()
,
puts()
Each function has its own subtleties
You MUST learn how to use these functions!Slide7
Formatted Output
printf
(“format”,
args
...);
Format contains format
specifiers
, such as %d (integer), %s (string), %c (character)
There must be an argument for every
specifier
Format can contain output modifiers such as \n to insert a newline
printf
(“%d is %s than %d\n”,
i
[0], “smaller”, max);Slide8
Conversions
s string
d signed integer
f float (double)
c single character
p pointer
Many others exist for alternative numeric formats
n displays the number of characters printed so farSlide9
ALL the Conversions ...
%c The character format
specifier
.
%d The integer format
specifier
.
%
i
The integer format
specifier
(same as %d).
%f The floating-point format
specifier
.
%e The scientific notation format
specifier
.
%E The scientific notation format
specifier
.
%g Uses %f or %e, whichever result is shorter.
%G Uses %f or %E, whichever result is shorter.
%o The unsigned octal format
specifier
.
%s The string format
specifier
.
%u The unsigned integer format
specifier
.
%x The unsigned hexadecimal format
specifier
.
%X The unsigned hexadecimal format
specifier
.
%p Displays the corresponding argument that is a pointer.
%n Records the number of characters written so far.
%% Outputs a percent sign.Slide10
Format Specifiers
%
flags (0ptional): sign, zero padding, etc.
minimum width (optional)
.precision (optional): maximum chars
length modifier (optional): short, long
argument type conversion: string, pointer, character, float, integer, etc.
%-2.8hs, %d, %*sSlide11
Examples of Output
printf
("Hello World\n");
char
buf
[256];
sprintf
(
buf
,"%8d\t%8d", a, b);
fprintf
(
stderr
,
"%s: fatal: %s not found",
argv
[0],
argv
[1]);
FILE *log =
fopen
("
log.txt","w
+");
fprintf
(log,"%s: %s\n", time,
msg
);Slide12
File Mode Values
"r" read
"w" write
"a" append
"r+" reading and writing
"w+" create then reading and writing and discard previous contents
"a+" open or create and do writing at endSlide13
C Input
To match
fprintf
()
for output there is
fscanf
(
file,fmt,args
)
for input. E.g.,
fscanf
(
stdin
, “%s %d”, name, &grade);
Format
specifiers
are pretty similar, but do have a few differences
Args
MUST be addresses
(pointers)
name
is a
char*
grade
is an
int
so we use its addressSlide14
scanf
()
ConversionsSlide15
More on Input
Various versions of
fscanf
()
exist
fscanf
(
stdin
,...)
same as
scanf
(...)
scanf
()
is hard to use at first!
Also have:
fgetc
()
,
getc
()
,
getchar
()
,
fgets
()
,
gets()
,
and
ungetc
()
Each function has its own little quirks
You must learn to use the
printf
()
and
scanf
()
families of functions!Slide16
/* Lab 1 Solution, Tami Meredith, 2011 */
#include <
stdio.h
>
#define debug 0
#define COUNT 10
#define SUCCESS 0
int
main (
int
argc
, char**
argv
) {
int
i
, data[COUNT], max = 0;
for (i = 0; i < COUNT; i++) {
scanf
("%d", &data[
i
]);
#if debug
printf
("%d: Read %d\n",
i
, data[
i
]);
#
endif
if (data[
i
] > data[max]) { max =
i
; }
}
printf
("Max = %d\n", data[max]);
return(SUCCESS);
} /* end main () */Slide17
C Operators
1.Parentheses ( ) [ ] L to R
1.Structure Access . -> R to L
2.Unary ! ~ ++ -- + - * & (
type
)
sizeof
L to R
3.Mult., Div., Modulus * / % L to R
4.Add, Subtract + - L to R
5.Shift << >> L to R
6.Comparison < <= > >= L to R
7.Equality == != L to R
8.Bitwise And & L to R
9.Bitwise
Exor
^ L to R
10.Bitwise Or | L to R
11.Logical And && L to R
12.Logical Or || L to R
13: Conditional ?= L to R
14.Assignment = += -= *= /= %= &= ~= |= <<= >>= R to L
15. Comma , L to RSlide18
Control Structures
if () ... , if () ... else ...
switch () { case _: ... default: ... }
for (;;) ..., while () ..., do { ... } while ();
break, continue
label:,
goto
f(), returnSlide19
Type Definitions
Type synonyms
Just an alternative name for a type
Often used to improve code portability
Type system uses structural equivalence, not name equivalence
typedef
int
number;
int
x = 5;
number y;
y = x; /* Allowed, both are
ints
*/Slide20
Def before Use
All C variables must be defined (or declared) before they are used.
Good style is to put all variable definitions at the beginning of a function.
Was NOT originally block scoped and had only file and function scoping
Many C programmers do not use block scoping as a result (I don't)Slide21
PreDefined Namespaces
objects – "variables"
functions
typedef
names
enum
constants
labels
SUE tags
Fields per SUSlide22
Structures
A "class" with only data fields
Structure (and union,
enum
) "tags" have their own namespace
tags are optional – usually leave them out in a
typedef
typedef
struct
{
int
x, y;
}
t_point
;
t_point
origin = { 0, 0 };
printf
("x:
%d,
y:
%d\n",
origin.x
,
origin.y
);Slide23
Enumerations
A way of giving names to an ordered set of integers
typedef
enum
{
club = 0, diamond, spade, heart
}
t_suit
;
typedef
enum
{
ace = 1, two, ... , jack, queen, king,
}
t_kind
;
typedef
struct
{
t_kind
k;
t_suit
s;
}
t_card
;
t_card
card = { king, club };Slide24
Pointers
int
x = 5;
int
*p;
p = &x;
printf
("%d %d", x, *p);
* := "is a pointer" or "take value of"
& := "take address of"Slide25
Function Pointers
void
bsearch
(
const void *key,
const void *base,
size_t
n,
size_t
size,
int
(*
cmp
)(const void *
keyval
, const void *datum)
);
char data[256][64];
bsearch
("tami",data,64*
sizeof
(char),256,strcmp);Slide26
Complex Declarations
char **
argv
pointer to pointer to char
int
(*
daytab
)[13]
pointer to array[13] of
int
int
*
daytab
[13]
array[13] of pointer to
int
void *comp()
function return pointer to void
void (*comp)()
pointer to function returning voidSlide27
Insane Declarations
char (*(*x())[])()
function returning pointer to array[] of pointers to functions returning char
char(*(*x[3])())[5]
array[3] of pointers to functions returning pointer to array[5] of charsSlide28
Type Specifiers
New in ANSI C standard
Two exist
const
may be initialised but not used in any subsequent assignment
volatile
lookup the value of the variable on every single access, do not cache, store in a register, or use in optimisation
used for memory mapping
implementation dependent; no required semanticsSlide29
Storage Classes
auto
: give the variable automatic storage on the stack; can only be used in functions
register
: try to keep the variable in a register; may by ignored;
&
cannot be used on register variables
static
inside functions, the variable retains it value between function calls (heap variable, not stack)
outside functions, it indicates a variable declaration cannot be linked to other compilation units (files)
extern
: declare the variable; storage will be defined elsewhere and location determined at link timeSlide30
Program Execution
Preprocessing: Remove #directives
Compilation
Tokenisation: Stream of Tokens
Parsing: Abstract Syntax Tree
Semantic Analysis: Type checking etc.
Optimisation: Register Transfer Language
Code Generation and Optimisation
Linking: Produce a
relocatable
executable
Loading: Resolve virtual addresses
ExecutionSlide31
C Preprocessor Constructs
Trigraph
replacement:
Obscure compliance with ISO 646-1983 Invariant Code Set
Line Splicing:
Lines that end with \ are joined
File Inclusion:
#include
Macro Definition and Expansion:
#define
Conditional Compilation:
#if
Line Identification:
Insertion of
#line
constructs
Error Generation:
#error
causes CPP to write an error message
Pragmas
:
Implementation dependent PP commandsSlide32
Predefined CPP Names
__LINE__ current source line
__FILE__ current source file
__DATE__ date of compilation
__TIME__ time of compilation
__STDC__ 1 if CC is standard-conforming
Other names may be defined by the implementationSlide33
File Inclusion
You are encouraged to create your own include files containing: Macros, Declarations,
Typedefs
, Types, etc.
Included files should not contain executable code!
Two Variants
#include <
file
>
Searches in the compilers include path for
file
#include "
file
"
Searches in a path from the CWD for
fileSlide34
Libraries 1
assert.h
: the
assert()
diagnostic macro
ctype.h
: character class tests
errno.h
: declaration of
int
errno
;
float.h
: implementation limits for floats
limits.h
: implementation limits for integers
locale.h
: localization information
math.h
: mathematical functions
setjmp.h
: non-local jumps to avoid normal function calls and returnsSlide35
Libraries 2
signal.h
: signal handling and raising
stdarg.h
: variable
arg
lists for functions
stddef.h
: std. type
defs
(NULL,
size_t
, ...)
stdio.h
: I/O, 1/3 of the C library
stdlib.h
: utility (conversion, storage
alloc
.)
string.h
: string manipulation
time.h
: time and date functionsSlide36
Macros
Not recursive, but
args
expanded/called multiple times
Two variants:
#define
identfier
token-sequence
e.g.:
#define loop while (1)
#define COUNT 20
#define
identifier
(
args
)
token-sequence
e.g.:
#define max((a),(b)) (((a)>(b))?(a)
:(b))Slide37
Macro Quirks
#
undef
will
undefine
a macro
e.g.: #
undef
COUNT
Macros can be redefined if desired
Token concatenation is allowed in macro bodies
e.g.,
#define cat(
x,y
) x ## y
cat(var,123)
produces
var123
#
arg
as a use causes
stringification
e.g.,
#define string(x) #x
string(hi\n)
produces
"hi\n"Slide38
Preprocessor Summary
#define COUNT 10
#define
MAX(
x,y
) (((x)>(y))?(x):(y))
#
undef
COUNT
#include <
stdio.h
>
#include "
myjunk.h
“
#
ifdef
CONST
ccode
#
endif
-- also
ifndef
#if defined(CONST)
ccode
#
endif
#if (1)
ccode
#
endif
#
elif
, #elseSlide39
GCC Flags
-Ox Use optimisation level x= 0,1,2,3 (none to most)
-c compile, do not link
-E preprocess only
-S generate assembly language
-o
name
rename the output to
name
-Wall Issue all warnings
-g Enable debugging support
-
ggdb
Enable
gdb
support
There are several hundred command line flags, these are just a few of the common ones you will use
Debugging + optimisation can yield very strange results, best to turn optimisation off when debuggingSlide40
Makefiles
makefiles
automatically build your program in Unix environments
lab1: lab1.c
gcc
–o lab1 lab1.c
Format of entries in
makefile
file
:
dependencies
<tab>
command
To use type:
make
Will use the first entry as the target by defaultSlide41
# Sample
Makefile
# By: Tami Meredith
a
ll: foobar.exe
clean:
rm
–f foobar.exe *.o
OBJS =
foo.o
bar.o
FLAGS = -Wall –O3
foobar.exe: $(OBJS)
gcc
-o foobar.exe $(FLAGS) $(OBJS)
f
oo.o
:
foo.c
gcc
–c
–o
foo.o
$(FLAGS)
foo
.c
bar.o
:
bar.c
gcc
–c –o
bar.o
$(FLAGS)
bar.c
fb.h
:
touch *.cSlide42
Good Code
Simple, clear
Readable, understandable
Maintainable
Efficient, but only sacrifice readability and maintainability if the efficiency is critical
Uniform with regard to coding standard
Comments are "value added"
Neither under nor over commentedSlide43
Coding Thoughts 1
Write it once only; if you duplicate code then
refactor
! (#bugs = LOC)
No magic numbers; use symbolic constants
Check for errors!
Clarity before efficiency unless needed
Trust the compiler to optimise for you
Make things explicit; casts not conversions
Aim for type consistency as much as possible
Use coding standards consistentlySlide44
Coding Thoughts 2
Know your hardware (e.g.,
sizeof
(
int
)
)
Use
sizeof
instead of explicit numeric values
You may need to
fflush
(
stdout
)
to ensure you see all your debugging output
If you modify any
typedef
, you must recompile the entire program
Don't delete code! Hide it with:
#if 0
... code ...
#
endif
Keep backups! Make checkpoints; consider using a repository (e.g., subversion)
Comments cannot be nestedSlide45
Abstract Data Types
Separation of interface and implementation
Predates OOP, Classes
Requires programmer compliance/honesty
E.g., stack, binary tree, hash table
Only have Arrays, SUEs to create composite data types
Interface:
predefined functions, SUEs, and types in the "public" header file
Implementation:
function definitions in the C file
possible second "private" header file with implementation-specific SUEs, types, and declarationsSlide46
A Simple List
/* Private type declaration */
typedef
struct
listruct
{
void *data;
struct
listruct
*next;
} list;
/* Public Interface */
list *
newList
(void);
void *car(list *l);
list *
cdr
(list *l);
list *cons(void *d, list *l);
int
length(list *l);
int
isEmpty
(list *l);Slide47
Hungarian Notation (Charles Simonyi)
Two variations exist
Systems Hungarian:
Prefix identifiers with their actual physical data type
e.g.,
piSum
= pointer to an integer
Application Hungarian:
Prefix identifiers with some useful semantic information
e.g.,
dVertical
= difference/delta,
rwVal
= rowSlide48
CLI Development on CS
Editor: vi, vim
Compiler, Linker, PP:
gcc
Text tools: AWK,
perl
, m4
Building: make,
cmake
,
imake
Search:
grep
,
egrep
,
fgrep
Comparision
: diff, diff3
Debugging:
gdb
, lint
Profiling:
gprof
Repository: subversion,
cvs
,
rcs
Unix tools: bash, sort,
uniq
, ...Slide49
/*
* Tami Meredith: Class Example: Pipes
*/
#include <sys/
types.h
>
#include <
errno.h
>
#include <
unistd.h
>
#include <
stdio.h
>
#include <
string.h
>
#include <
stdlib.h
>
#define BUFSIZE 64
#define READING 0
#define WRITING 1
/* A variation on
perror
() */
void
failure (
msg
)
char *
msg
;
{
fprintf
(
stderr
, "%s: error %d\n",
msg
,
errno
);
exit(EXIT_FAILURE);
} /* end failure () */Slide50
int
main (
argc
,
argv
)
int
argc
;
char **
argv
;
{
int
main (
int
argc
, char **
argv
)
{
int
main (
int
argc
, char **
argv
) {
int
main (
int
argc
, char **
argv
) {
int
main (
int
argc
, char **
argv
) {
/* space after name in dec/def, not in use to help search
e.g.: main(2,{"a.exe"}); */Slide51
int
main (
int
argc
, char **
argv
) {
pid_t
pid
;
int
p[2],
i
, sum = 0;
char
buf
[BUFSIZE];
/* Create pipe BEFORE we fork (so both have it) */
if (pipe(p) == -1) { failure ("pipe allocation failure"); }
for (i = 0; i < 10; i++)
{
if ((
pid
= fork()) == -1) { failure ("can't fork"); }
if (
pid
== 0)
{ /* Child process writes */
sprintf
(
buf
, "%d",
getpid
());
write(p[WRITING],
buf
,
strlen
(
buf
)+1);
exit(EXIT_SUCCESS);
} else { /* Parent reads */
read(p[READING],
buf
, BUFSIZE);
sscanf
(
buf
,"%
d",&pid
);
sum = sum +
pid
;
}
}
printf
("Average is %f\n", sum/10.0);
exit(EXIT_SUCCESS);
} /* end main () */