Transcript Lecture 3
CS 3034 Lecture 3
Introduction To C
Many of these slides were originally
written by Henning Schulzrinne,
Columbia University
C, C++, and Java
C
Developed by Dennis Ritchie in late 1960s/ early 1970s
Designed for systems programming
Original purpose was to develop UNIX
Low level enough for OS programming, high level enough for code to be
reasonably portable across hardware platforms (can’t do this in Assembly)
Applications could be written in Fortran, PL/I, etc.
Still the standard in systems programming
Linux kernel is strictly in C
2
Schulzrinne
C, C++, and Java
C++
Bjarne Stroustrup (Bell Labs), 1980s
Superset of C; note the pun in the name
• Adds support for OOP
• Adds higher-level I/O and other functionality
3
Schulzrinne
C, C++, and Java
Java
James Gosling in 1990s, originally for embedded systems, found many
uses
object-oriented, like C++
ideas and most syntax from C / C++
more platform independent than C++ due to use of JVM
easier to use than C++ but gives up some of C++'s low-level functionality
protects from many typical C/C++ errors
4
Schulzrinne
C vs. C++
Both very common in Windows, Linux
C++ adds OOP capabilities to C
Both less portable than Java
C++ has simpler I/O than C
Both can be hard to read, and both encourage
"clever" programming over code readability
Fewer “guard rails” than Java; it is much easier to
make serious logic errors in C/C++ than in Java
5
Schulzrinne
K&R
This book, known as “K & R,” is the Bible of C and served
as the informal standard for C in the early days.
K & R is a detailed reference book. You don’t need it and
generally wouldn’t find it very useful for this course.
However, if you talk about C to other programmers, it
won’t be long before someone mentions it, so you need to
know what it is. If you ever work as a C programmer,
everyone will expect you to have a copy.
6
Introduction To C
These introductory slides are intended for students who
are already proficient in Java.
I will skip over many topics that are substantially the same
in C as in Java.
7
Why Learn C / C++?
C++ is very widely used in application programming, C in
systems programming
Support both high-level and low-level programming
OS: user interface to kernel to device driver
Better control of low-level mechanisms
memory allocation, specific memory locations
Performance often better than Java
compiled, not run on a VM
usually more predictable due to lack of JVM layer (also: C vs. C++)
8
Schulzrinne
Why learn C, cont’d.
Much older code is written in C or C++
Linux, *BSD
Windows
Embedded systems are usually written in C
Schulzrinne
Executing C programs
Scripting languages are usually interpreted
perl (python, Tcl) reads script, and executes it
sometimes, just-in-time compilation – invisible to
user
Java programs semi-interpreted:
javac converts foo.java into foo.class
not machine-specific
byte codes are then interpreted by JVM
C programs are normally compiled and linked:
gcc converts foo.c into a.out or, with an
extra parameter to the compiler,
just foo
Schulzrinne
a.out or foo is executed by OS and hardware
C vs. Java
Java program
collection of classes
class containing main method is starting class
running java StartClass invokes
StartClass.main method
JVM loads other classes as required
Schulzrinne
C program
collection of functions
one function – main() – is starting
function
running executable (default name a.out)
starts main function
typically, single program with all user code
linked in – but can be dynamic libraries (.dll,
.so)
Schulzrinne
C vs. Java
public class hello
{
public static void main
(String args []) {
System.out.println
("Hello world");
}
}
Schulzrinne
#include <stdio.h>
int main(int argc, char
*argv[])
{
puts("Hello, World");
return 0;
}
Basic C Output
puts(string parameter)
putchar (char parameter)
printf with formatting codes
codetype format
d int decimal (base ten) number
o int octal number (no leading '0' supplied in printf)
x or X
int hexadecimal number (no leading '0x' supplied in printf; accepted if present in
scanf) (for printf, 'X' makes it use upper case for the digits ABCDEF)
ld long decimal number ('l' can be applied to any of the above to change the type from 'int'
to 'long')
u unsigned decimal number
lu unsigned long decimal number
c
char [footnote]
single character
s
char pointer string
f
float [footnote]
number with six digits of precision
g
float [footnote]
number with up to six digits of precision
e
float [footnote]
number with up to six digits of precision, scientific notation
lf double [footnote] number with six digits of precision
lg double [footnote] number with up to six digits of precision
le http://www.cdf.toronto.edu/~ajr/209/notes/printf.html
double [footnote] number with up to six digits of precision, scientific notation
Basic C Output
printf formatting codes can take digit values to specify
precision
float PI = 3.14159;
printf("%4.3f\n", PI); //prints 4 digits, with 3 after the decimal point
Simple example
#include <stdio.h>
int main(void)
{
printf("Hello World. \n \t and you ! \n ");
/* print out a message */
return 0;
}
If you are using a text editor or IDE in which the console screen
disappears after execution, add getchar();
After the output. This will cause the program to wait for input so
that the console stays open.
Schulzrinne
Dissecting the example
#include <stdio.h>
include header file stdio.h, which contains code
needed for the printf()
# lines processed by pre-processor
No semicolon at end
Lower-case letters only – C is case-sensitive
void main(void){ … } is the only code executed
printf(" /* message you want printed */ ");
\n = newline, \t = tab
\ in front of other special characters within printf.
Schulzrinne
printf("Have you heard of \"The Rock\" ? \n");
Executing the C program
int main(int argc, char argv[])
argc is the argument count
argv is the argument vector
array of strings with command-line arguments
the int value is the return value
convention: 0 means success, > 0 some error
can also declare as void (no return value)
Schulzrinne
Executing a C program
Name of executable + space-separated
arguments
$ ./myprog 1 23 ‘third arg’
argv
argc
4
a.out
Schulzrinne
1
23
"third arg"
Executing a C program
If no arguments, simplify:
int main() {
puts("Hello World");
exit(0);
}
Uses exit() instead of return – same
thing.
Schulzrinne
The C compiler gcc
There are many compilers available for C, but use gcc, the
gnu compiler collection. Includes compilers for many
languages, plus an assembler. Since C and C++ compilers
are not fully standardized, it is important that you use the
same compiler I use to grade your work.
Don’t confuse the compiler with an IDE. The compiler only
compiles. IDEs contain text editors, etc. and use
compilers when needed.
Use any IDE you want for this course. Some of my demos
will use Geany, which is available for Windows, Linux, and
OSX.
Schulzrinne
gcc
If you use Linux or OSX, gcc was probably already
installed with your OS
If it is not already installed in your Fedora VM or
other Fedora machine, install it this way:
sudo dnf install gcc
For Windows, install mingw from
http://www.mingw.org/
then find the gcc executable and *carefully* add the
directory to your path
If you write your code on your own machine, recompile
and test it in the Fedora VM before you turn it in!
Schulzrinne
gcc
C++ compilers will compile C code, but not the other way
around. At this point, you should deliberately compile as
C, not C++, to make sure you do not use C++ by accident.
gcc invokes C compiler
gcc translates C program into executable for some target
default file name a.out
$ gcc -std=c11 -m32 -Wall hello.c
$ ./a.out
Hello, World!
-Wall adds warning messages
-std=c11 directs the compiler to treat the code using C 2011, the most recent
specification.
To give a better name to the executable, add -o and the desired file name, eg
gcc -std=c11 -m32 -Wall -o hello hello.c
Schulzrinne
The C compiler gcc
Most text editors have menu items to compile, build, and execute
programs, so that they can be used as lightweight IDEs. Often the
menu items will already have the right commands for gcc, based on
the filename extension c or cpp. If you have to set them, the right
commands are typically:
Compile: gcc -std=c11 -m32 -Wall -o "%e" "%f"
Execute: "./%e"
Error reporting in gcc
Multiple sources
preprocessor: missing include files
parser: syntax errors
assembler: rare
linker: missing libraries
Schulzrinne
Error reporting in gcc
If gcc gets confused, hundreds of
messages
fix the first one, and then retry – ignore the
rest
gcc will produce an executable with
warnings
don’t ignore warnings – compiler choice is
often not what you had in mind
Compilers can’t identify logic errors!
if (x = 0)
Schulzrinne
vs. if
(x == 0)
gcc errors
Produces object code for each module
Assumes references to external names
(variables, etc from imported files) will be
resolved later
Undefined names will be reported when
linking:
undefined symbol
first referenced in file
_print
program.o
ld fatal: Symbol referencing errors
No output written to file.
Schulzrinne
C preprocessor
The C preprocessor (cpp) is a macroprocessor which
manages a collection of macro definitions
reads a C program and transforms it
Example:
#define MAXVALUE 100
#define check(x) ((x) < MAXVALUE)
if (check(i) { …}
becomes
if ((i) < 100)
Schulzrinne
{…}
C preprocessor
Preprocessor directives start with # at
beginning of line:
define new macros
input files with C code (typically, definitions)
conditionally compile parts of file
gcc –E shows output of preprocessor
Can be used independently of compiler
Schulzrinne
C preprocessor
#define name const-expression
#define name (param1,param2,…) expression
#undef symbol
replaces name with constant or expression
textual substitution
symbolic names for global constants
type-independent code
Schulzrinne
C preprocessor –file inclusion
#include "filename.h"
#include <filename.h>
inserts contents of filename into file to be compiled
"filename" relative to current directory
<filename> relative to /usr/include
gcc –I flag to re-define default
import function prototypes (cf. Java import)
Examples:
#include <stdio.h>
#include "mydefs.h"
#include "/home/alice/program/defs.h"
Schulzrinne
Comments
/* any text until */
// C++-style comments – careful!
– Only added to C in 1999
Convention for longer comments:
/*
* AverageGrade()
* Given an array of grades, compute the average.
*/
Avoid **** boxes – hard to edit, usually
look ragged.
Schulzrinne
Naming Conventions
Naming conventions are looser for C than
for Java.
– Some programmers use camel case, as in
Java: myVariable
– Others use the traditional C style, with
underscores: my_variable
– Use all caps for constants: PI
– Most important: be consistent within
your own code
Schulzrinne
type
bytes
(typ.)
range
char
1
-128 … 127
short
2
-65536…65535
int
4
(usually)
-2,147,483,648 to 2,147,483,647
long
8
264
float
4
3.4E+/-38 (7 digits)
double
8
1.7E+/-308 (15 digits)
Schulzrinne
Numeric data types
Remarks on data types
Range differs – int is usually 32 bits, may
be 16 or 64 on some systems with come
compilers. Try this:
– printf("%lu\n", sizeof(int)); //lu means “long
unsigned”
Also, unsigned versions of integer types
same bits, different interpretation
char = 1 ASCII "character"
Schulzrinne
Scanf
Opposite of printf, with formatting codes
Take the & in format codes on faith for now.
If you enter a string, scanf stops reading at
any whitespace
Schulzrinne
Example
#include <stdio.h>
void main(void)
{
int nstudents = 0; /* Initialization, required */
printf("How many students does Columbia have ?:");
scanf ("%d", &nstudents); /* Read input */
printf("Columbia has %d students.\n", nstudents);
return ;
}
$ How many students does Columbia have ?: 20000 (enter)
Columbia has 20000 students.
Schulzrinne
Type conversion
#include <stdio.h>
void main(void)
{
int i,j = 12;
/* i not initialized, only j */
float f1,f2 = 1.2; /* f1 not initialized, only f2 */
printf("%d %d %f %f\n", i, j, f1, f2);
i = (int) f2;
/* explicit: i <- 1, 0.2 lost */
f1 = i;
/* implicit: f1 <- 1.0 */
printf("%d %d %f %f\n", i, j, f1, f2);
f1 = f2 + (int) j; /* explicit: f1 <- 1.2 + 12.0 */
f1 = f2 + j;
/* implicit: f1 <- 1.2 + 12.0 */
printf("%d %d %f %f\n", i, j, f1, f2);
}
Schulzrinne
Explicit and implicit conversions
Implicit: e.g., s = a (int) + b (char)
Promotion: char -> short -> int -> …
If one operand is double, the other is made
double
If either is float, the other is made float, etc.
Explicit: type casting – (type)
Almost any conversion does something – but
not necessarily what you intended
Schulzrinne
Type conversion
int x = 100000;
short s;
s = x;
printf("%d %d\n", x, s);
100000 -31072
Cast to short preserves the lower 16 bits, which are 1000011010100000,
as a twos complement representation. Decimal value of twos
complement value 1000011010100000 is -31072
Schulzrinne
booleans
Booleans in C require #include <stdbool.h>
There is no printf formatting code for booleans, so you have to be
a little creative.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
bool b = false;
printf("%s\n", b?"true":"false");
return 1;
}
Or
puts(b?"True":"False");
User-defined types
typedef gives names to types:
typedef short int small_number;
typedef unsigned char byte;
typedef char String[100];
small_number x;
byte b;
String name;
Schulzrinne
Constants
The const keyword (equivalent to final in Java) makes a
value a constant
const float PI = 3.14159;
PI = 5;
// syntax error!
Enumerated types
Just syntactic sugar for ordered collection of
integer constants:
typedef enum {
Red, Orange, Yellow
} Color;
is like
#define Red 0
#define Orange 1
#define Yellow 2
Schulzrinne
Enumerated types
This more Java-like syntax also works:
enum monster {ZOMBIE, VAMPIRE, YETI};
enum monster curr_monster = VAMPIRE;
Output as int, or use conditionals to print strings
printf("%d\n", currmonster);
Or
if(curr_monster == VAMPIRE) puts ("Watch out, he's a
Vampire!");
Etc.
The switch statement
Allows choice based on a single value
switch(expression) {
case const1: statements1; break;
case const2: statements2; break;
default: statementsn;
}
Effect: evaluates integer expression
– But more things count as ints than you might
think: enums, chars, etc.
looks for case with matching value
executes corresponding statements (or
defaults)
Schulzrinne
switch
#include <stdio.h>
void main(void)
{
typedef enum {ZOMBIE, VAMPIRE, WEREWOLF} Monster;
Monster m = WEREWOLF;
switch(m) {
case ZOMBIE:
printf("Zombie; get shotgun\n");
break;
case VAMPIRE:
printf("Vampire; get wood stakes\n");
break;
case WEREWOLF:
printf("Werewolf; get chocolate\n");
break;
default:
printf("Unknown monster; call in Godzilla\n");
}
}