a c++ crash course
DESCRIPTION
A C++ Crash Course. UW Association for Computing Machinery http://www.cs.washington.edu/orgs/acm/tutorials [email protected]. Questions & Feedback to Hannah C. Tang (hctang) and Albert J. Wong (awong). Goals of Java. Java Simple Consistent Huge OO Focus - PowerPoint PPT PresentationTRANSCRIPT
A C++ Crash Course
UW Association for Computing Machinery
http://www.cs.washington.edu/orgs/acm/tutorials
Questions & Feedback to Hannah C. Tang (hctang) and Albert J. Wong (awong)
Goals of Java
Java– Simple– Consistent– Huge OO Focus– Cross platform via a virtual machine– Originally for embedded systems
Java, C, and C++, have different design goals.
Goals of C and C++
C– Low level– No Runtime Type info– Easy implementation
C++– Originally to add some OO functionality to C– Attempt to be a higher-level language– Now it’s a totally different language
C and C++ are popular because they have met, with reasonable success, their goals.
The compilation Process
Preprocessor
.c .h .c .h
Compiler
Linker
executable
Libraries
Source code (text)
C/C++ code (text)
Object code (bin)
Native Executable (bin)
PreprocesserResolves #define, #include
CompilerTranslates code to Machine Language. It outputs an “object file.” This code is not executable
LinkerTakes object files and resolves references to functions and variables in different files
Declarations - (bad) Example
int main(void) {int result;...
result = add(20, 3);
...return 0;
}
int add(int a, int b) {return a + b;
}
What is wrong with the following code? Will it compile in C? in C++?
Hint: It has to do with the declaration and use of add.
Declaration Regions
int main(void) {int result;int add(int,int);...
result = add(20, 3);
...return 0;
}
int add(int a, int b) {return a + b;
}...
int add(int,int);
int main(void) {int result;...
result = add(20, 3);
...return 0;
}
int add(int a, int b) {return a + b;
}...
add is declared in the shaded
regions
Corrected Code 1 (local prototype)
Corrected Code 2 (global prototype)
#define • #define Tag Substitution
– Replaces all following occurrences of Tag with Substitution– The Substitution may be the empty string– Does not replace Tag if it is inside quotation marks
• #define Tag(x,y,z) Substitution– Creates a Function-like macro Tag– The Substitution may refer to the parameters x, y, or z– Only items of the form Tag(x,y,z) will be replaced (Just plain Tag will be ignored)
#define MAX_SIZE 80#define GET_FIELD(a,b) a->b
int ar[MAX_SIZE];GET_FIELD(point, xCoord);GET_FIELD(“lalala", f03j?);
int ar[80];point->xCoord “lalala”->f03j?
Header FilesCommon Usages:• Creates an informal module interface (No relation to
Java interfaces)• Provides documentation• Each module usually has a header file• Often include the following:
– function prototypes– struct and class declarations– typedefs– global variable declarations– Lots of (high-level) comments
• Abstracts code for optimization (less common)
#include#include essentially copies and pastes the given
file into the current line
• There are two forms of #include• They differ in the order in which directories are search
for the given file• The search order is implementation defined• Here is the general pattern for different compilers:
#include <filename>• Searches the “include path,” then the current directory
#include “filename”• Searches the current directory, then the “include path”
Header Guards
Wrap each header file with the lines:
#ifndef FILENAME_H
#define FILENAME_H
<header file body here>
#endif /* FILENAME_H */
Header Guards are a common C/C++ idiom
There is almost no reason to put things outside of header guards
Header Filepoint2d.h
#ifndef POINT2D_H#define POINT2D_H
struct Point2D { int x; int y; };typedef struct Point2D Point2D;
/* returns the result of the vector addition of * a and b. */Point2D add(Point2D *a, Point2D *b);
/* returns the result of the vector subtraction of * b from a */Point2D sub(Point2D *a, Point2D *b);
#endif /* POINT2D_H */
Classes• Roots come from C-style structs• Fairly similar to Java classes in concept.• Used to group related data and functions.• Can be used to write OO code
class Queue {public:
Queue();void enqueue(int n);int dequeue();~Queue();
private:int numElements;int capacity;int *queueData;
};
Basic class Syntax
Declaring a class: class [optional name] {
[access modifier]<type> member1;<type> member2;
[access modifier]<type> member3;<type> member4;…
} [instance list];
Example: class Point2D{
private:int x;int y;
public:Point2D(int x, int
y);int getX();int getY();
} p1(2,3);
Point2D p2(1,3);Point2D *p;
Declaring a class without inheritance
/* point2d.h */
#ifndef POINT2D_H#define POINT2D_H
class Point2D{private:
int x;int y;
public:Point2D(int x, int
y);int getX();int getY();
};
#endif /* POINT2D_H */
Declaring & Defining methods/* point2d.cc */
#include “point2d.h”
Point2D::Point2D(int x, int y){x = 0; y = 0;
}
int Point2D::getX(){return x;
}
int Point2D::getY(){return y;
}
Classes form a closed namespace
Constructors
• Constructors have the same name as their class• Constructors may not pass off control to another
constructor• A default (zero argument) constructor is
provided when no other constructors declared• Constructors may invoke the constructors of
their super class, and of their member variables via member-wise initialization.
Constructors are functions that get called when a class is instantiated
DestructorsDestructors are called when a class is deallocated
• Destructors are have no return type and have the same name as their class with a ‘~’ prepended.
• If no destructor is given, a trivial destructor, which calls the destructor for all elements is given.
InheritanceInheritance is specified by a : and a list of access specifiers + class names in the class declaration
class Point2D{private:
int x;int y;
public:Point2D(int x, int
y);int getX();int getY();
};
class ColorPoint2D : public Point2D
{private:
int color;
public:ColorPoint2D(int
x, int y, int
color);int getColor();
};
Inheritance continued
• Base classes can be public, protected, or private– In public inheritance, all public and protected
members are inherited– In protected inheritance, all public members from the
base class become protected– In private inheritance, all public and protected
members become private
• Java only has public inheritance• You can call any ancestor’s class method using
the scope resolution operator (::)
Dynamic Memory
• Dynamically sized memory in C and C++ must be manually managed
• Dynamic memory is not necessarily much slower than static memory
• All allocated memory must be freed by the user• Do not free memory twice (double free).• Do not free memory that was allocated by you• Manual memory management allows for finer
grained control of your program• It’s not that scary, nor that hard.
new, delete, delete[]
• the new operator allocates new memory, initializes it and returns a pointer to it.
• the delete operator deallocates memory allocated by new
• If you allocate a new array, you must delete it with delete[] and not delete
Improper use of delete and delete[] will cause undefined behavior!
Point2D *p = new Point;delete p;p = NULL;
int *ar = new int[50];delete[] ar;ar = NULL;
Example:
malloc, calloc, realloc, free• These are C memory management functions• Do not mix them with the C++ ones! (that is, don’t
try to delete memory from malloc, etc.)• These functions return void* (pointers to anything)• They are not typesafe• They do not call initializers for the memory• There is no realloc equivalent for C++• Some low-level memory management may be
faster with these functions, but don’t bank on that.
Arrays
• Arrays are contiguous memory locations, and its name refers only to the address of the first element
• Indexing into an array is the same as adding an offset to the address of the first element
• When declaring an array, its size must be known at compile-time
myArray[0] or myArray
myArray[1]
myArray[2]
myArray[3]
myArray[4]
myArray[5]
<ArrayType> arrayName[ numElements ]
Arrays as function parameters
• Arrays are not passed by copy. Instead, the address of the first element is passed to the function– Note how array parameters and non-
parameter arrays behave identically
<ReturnType> funcName( ArrayType arrName[ ] )
int sumOfArray( int values[], int numValues )
Pointers: vocabulary
• A pointer is a variable which contains addresses of other variables
• Accessing the data at the contained address is called “dereferencing a pointer” or “following a pointer”
n(4096)
y(4100)
x(4104)
4096
7
Pointer SyntaxDeclaring Pointers
Declaring a pointer: <Type> * ptrName;
“ptrName is a variable which contains the address of something of type <Type>”
For example:int * nPtr1, * nPtr2;void aFunc( int aParam, int * ptrParam);
Using Pointers
Dereferencing a pointer:*ptrName“Go to the address contained in the variable ptrName”
Getting the address of a variable:&aVar“Get the address of aVar”
For example:aFunc(myInt, &anotherInt);anInt = *myPtr * 4;*dinner = 100;
Pointers: Putting it all together
The code
int * p;
int q;
p = &q
*p = 5;
Box Diagrams
“p’s type is int pointer. q’s type is int.”
“Assign 5 to where p points (which is q).”
Memory Layout
p contains the address of an int. q contains an int.Go to the address that p contains, and place a 5 there.
5pp (8200) 8196
q (8196) 5q
Pointer Arithmetic
Pointers are numbers, so you can do math on them!
200
9
8192p
(8200)
b (8196)
a (8192)
int * p = &a;
Pointer p refers to an int, so adding 1 to p increments the address by the size of one int. The C/C++ expression for this is sizeof(int)
200
300
8192p
(8200)
b (8196)
a (8192)16
9
8192p
(8200)
b (8196)
a (8192)
*p = 200;
*(p+1) = 300;
Pointers and Arrays
Pointers and arrays are (almost) interchangeable
myArray[3](8196)
myArray[4](9000)
int myArray[5];
int * p = myArray;
Given:
These are equivalent:• *p• myArray[0]• *(p+0)• *myArray• p[0]• 0[p]
myArray[2](8192)
myArray[1](8188)
myArray[0](8184)
p(8180)
8184
Function Pointers
• Functions are pieces of code in memory• Pointers can point to functions.• Notice that the name of the variable appears in
the middle of the statement!• You do not have to dereference a function
pointer
<ReturnType> (*ptrName)(arg type list );
Function pointers are not scary. They are useful!
Function Pointers - example
void foo(int i, char b);void bar(int i, char b);
int main(void) {void (*p)(int,char);
p = foo;p(1, ‘c’); // equivalent to foo(1, ’c’);
p = bar;p(2, ‘b’); // equivalent to bar(2, ‘b’);(*p)(2, ‘b’); // Exactly the same
return 0;}
C-style struct
A struct is used to group related data itemsstruct student {
int id;char name[80;]
};
• To the programmer– id and name are now related– struct student creates a convenient grouping
• To the compiler– Id and name have a fixed ordering (not offset) in memory– Struct student is a first-class type that can be passed to
functions
Note that the it is optional to name a struct
struct SyntaxDeclaring a Struct
Declaring a struct: struct [optional name] {
<type> field1;<type> field2;…
} [instance list];
Examples: struct Foo {
int field1;char field2;
} foo,*foo_ptr;
struct Foo foo2;
struct { int a; } blah;
Access struct fields
Accessing a field in a struct:foo.field1;
“gets field1 from the instance foo of struct Foo”
Pointers syntax and structsThe * has lower precedence than the ‘.’ :
*foo_ptr.field1; means
*(foo_ptr.field1);Which won’t compile
Accessing a field in a struct pointer: (*foo_ptr).field1;foo_ptr->field1;
Typedef
Typedef is used to create an alias to a type
• byte now represents an unsigned char
• Both definitions of mybyte are equivalent to the compiler.
• The second definition is preferred as it gives more info
typedef unsigned char byte;
byte mybyte;
unsigned char mybyte;
Typedefs – structs/enums/unionsPeople often make a typedef of an
anonymous struct or enum
typedef struct { int id;char name[80];
} Student;
Student st;
struct Student { int id;char name[80];
};
struct Student st;
These are almost the same. However, anonymous structs cannot refer to themselves.
struct List { int data;struct List *next;
};
C-style IO is an acquired taste. Learn to like it.
I/O C-style
Basic functions:• printf, scanf, fprintf, fscanf, sprintf, sscanf, etc.• gets, puts, getc, putc, getchar• read, write, fread, fwrite
We will cover the basics of the “formated” family of functions (printf, scanf, etc).
For the others, read the man pages in Unix.
printf(char *format_string, ...);fprintf(FILE*, char *format_string, ...);
snprintf(char* buf, size_t n, char *format_string, ...);
printf
• In C, all devices are treated like files• Three standard files are:
– stdin Often the keyboard– stdout Often the text console– stderr Often the text console
• printf(....) is fprintf(stdout, ....)• The format string is a pattern for the output; it describes how to
display the arguments to printf.• Snprintf write to the string “buf”. The variable n specifies the size of
the buffer.• printf returns the number of characters written
format string
• Format strings are normal strings with embedded “conversion specifications” which are placeholders for arguments
• Conversion specifications are a ‘%’ and a letter with an optional set of arguments in between the ‘%’ and letter.
• To print a ‘%’, you need to write ‘%%’
Example:printf(“Here is a number: %d\n”, 10);
%d is the conversion specification for signed integers.
Conversion Specifications
Conversion Specifications:• %d, %i -- signed integer• %u -- unsigned integer• %f -- floating point number• %c -- character• %s -- string• %x -- hexadecimal value• %p -- pointer
Converion specifications tell how to translate a data value into a string
Options:• l -- long (32-bit value)• ll -- long long (64-bit value)• n -- field width of n digits• .n -- precision of n digits• 0 -- fill unused field with 0s
There are many more! Read man pages, or Google it.
C++-style IO is easier for simple stuff
I/O C++-style
Basic classes:• iostream (cout, cin, cerr)• ostringstream, istringstream
cout << “Hello World!” << endll;cout << “Boo! “ << 10 << ‘c’ << endl;cerr << “Here’s the error stream” << endl;
int n;cin >> n;
char ch;cin >> ch;
...but harder for complex stuff
I/O C++-style continued...
printf(“%.3f rounded to 2 decimals is %.2f\n”, 2.325, 2.325);
…becomes…
cout << setprecision(3) << 2.325 << “ rounded to 2 decimals is “<< setprecision(2) << 2.3.25<< endl;
Global Variables• Global Variables are not evil!
• Allocated at program start.
• Deallocated at program end.
• By default, initialized to bit-wise zero (do not depend on this).
• Need to understand modifiers: extern, static, and const to use properly.
• Need to understand linking to use properly.
Global Variables - Gotcha
/* util.c */
int g_numCalls = 0;
void someFunc(void) {fprintf(stderr, “Num Calls to %s: %d\n”, __func__, g_numCalls);...
}
What is wrong with this code?
/* test.c */void someFunc(void);int g_numCalls = 0;
int main(void) {fprintf(stderr, “Num Calls to %s: %d\n”, __func__, g_numCalls);
someFunc(); someFunc();...
}
compile line: gcc -Wall -ansi util.c test.c -o test
static
On a global variable or a functionstatic int g_someGlobalVariable;static void myFunction(void);Tells the linker not to export the variable or function. Essentially makes the identifier “file scope,” as the linker will not use it fulfill dependencies from other files.
On a local (function) variablevoid someFunc(void) {
static int array[4000];}Places the variable off the stack. This has the side-effect that it retains it value across calls. It is often used when a variable is too large to be put on the stack.
On a class member (covered when we discuss classes)
static has 3 very separate meanings
Globals Variables - Gotcha (fixed)
/* util.c */
static int g_numCalls = 0;
void someFunc(void) {fprintf(stderr, “Num Calls to %s: %d\n”, __func__, g_numCalls);...
}
Static to the rescue!!!!!
/* test.c */void someFunc(void);static int g_numCalls = 0;
int main(void) {fprintf(stderr, “Num Calls to %s: %d\n”, __func__, g_numCalls);
someFunc(); someFunc();...
}
compile line: gcc -Wall -ansi util.c test.c -o test
The two variables “g_numCalls” have no relation. Think of them as private to each file.