830 likes | 939 Views
CSE 380 – Computer Game Programming C++ Boot Camp. BioShock by 2K Games, 2007. Looking for a good reference?. http://www.cplusplus.com/doc/tutorial/introduction/. What is memory?. Think of it as a giant array How do we assign data to/get data from memory? memory addresses
E N D
CSE 380 – Computer Game ProgrammingC++ Boot Camp BioShock by 2K Games, 2007
Looking for a good reference? http://www.cplusplus.com/doc/tutorial/introduction/
What is memory? • Think of it as a giant array • How do we assign data to/get data from memory? • memory addresses • i.e. indices into memory array • addresses are typically byte addressable 0xffffffff Stack Segment Heap Segment 0x10000000 Global Segment Text Segment 0x00000000
What goes in each memory segment? • Stack Segment • local variables (includes arguments) • Heap Segment • instance variables • Global Segment • data that is known at compile time • Ex: String Literals like “Hello” • global variables (only one of each) • Text Segment • program instructions Stack Segment Heap Segment Global Segment Text Segment
Why do we care about this? • This is important to understand proper data manipulation • Be careful where you put your data! • Data put on the stack disappears when the method returns!
Why are we here? • To prevent C & C++ from becoming the obstacle to learning to build game technologies • What will we cover? • Text • Arrays & structs • Pointers Call by Value vs Call by Reference • Objects & classes • Inheritance
Some reasons why C++ can be painful • Multiple flavors • Each platform has its own compiler • each has its own ways of doing things • For VS2010, you’ll make 2 types of source files: • .h : header files • .cpp : c++ source files
Let’s Start With a VS2010 Tutorial • Go to the class schedule page • For Wed., you’ll see a VS 2010 tutorial • Open that page and follow along
Make the BankFramework Project • Win32 Project • Visual C++ • “CSE380_Cpp_BootCamp” Solution • Put project in solution dir • Make it a static library project
Windows Dev. File Types • Source Code: • Header files (.h) • Source files (.cpp) • Built Files: • Static Libraries (.lib) • Execuitable Apps (.exe) • Dynamic Link Libraries (.dll)
Stuff we won’t touch • VS 2010-generated files: • VS 2010 Solution Files (.sln) • Solution Database/settings files (.ncb & .sdf) • VS 2010 Project Files (.vcxproj) • Object Files (.obj) • Precompiled Header Files (.pch) • Lots of other junk
Project Directory Structure • Note, this is my own style: • SolutionDir • Apps (where our own .exe files go) • /ProjectName/ProjectName.exe • Common (where our own .lib files go) • ProjectName.lib • ProjectName • ProjectName.vcxproj • /ProjectNameSourceCode/…cpp & .h • Temp (Intermediate Dir)
VS 2010 Macros • $(SolutionDir) • $(ProjectDir) • $(ProjectName) • $(Configuration) • $(IntDir) • $(OutDir) • $(TargetName) • $(TargetExt)
Why do linker errors happen? • 1. A header file says a method is available, but it’s never defined • may be spelled incorrectly, maybe scoped incorrectly, or not scoped at all • 2. VS 2010 doesn’t know where to look for a .lib file • 3. VS 2010 doesn’t know which .lib file to link to
Setup Directory Structure • Select Output Location • Select a Temp Directory • Group VS2010-generated source files • Add a Source directory to your project • Add a Filter • Add Account and Bank Classes
What’s a wchar_t? • A C++ type • It stores wide characters • Why not use char? • might not accommodate Unicode • in truth, windows uses wchar_t • they have their own similar type WCHAR • so we’ll use wchar_t for all text
And for strings of text? • We’ll use wstring • What’s that? • String of wide characters • And for num-text and text-num conversions? • we’ll use wstringstream • Look at BankConsoleApp
Exercise • Change the program such that it asks the user for data regarding the new Account • Owner and initial balance • Add the new account to the bank • Note, the bank accepts Account pointers. Ex: Account *a = new Account(ownerWstring, 1000);
Arrays • In C++, you can put an array on the stack void method() { int stackNums[5]; … • global region: int globalNums[5]; void method() {… • or the heap: int *heapNums = new int[5];
#include "stdafx.h" #include <string> using std::wstring; #include <iostream> using namespace std; #include <sstream> int _tmain() { int counter = 0; while (counter < 10000) { wstring text; std::wstringstream wss; wss << counter; text.append(L"Counter: "); text.append(wss.str()); text.append(L"\t"); wcout << text; wstring *textPointer = new wstring(); textPointer->append(L"Counter: "); textPointer->append(wss.str()); textPointer->append(L"\n"); wcout << (*textPointer); _sleep(1); counter++; } } Make a new Win32 Console Project • Run the program • Also, open the task manager (CTRL – ALT – DEL) • Is there a memory leak?
Ever used C? • Java inherited much from C • similar primitives (not entirely the same) • similar conditional statements • similar loops • But lots is different • pointers • structs • C memory management • and much more
What is a computer’s memory? • A sequential group of storage cells • typically a cell is a byte • Each cell has an address (a number) • In C as in Java • some cells contain data • some cells contain references to other memory addresses • memory addresses are typically 4 bytes
Pointers • In Java, what do object variables store? • memory addresses • this makes them pointers • what do they point to? • object data on the heap • In C, you can have either: • a pointer to a struct/array/primitive OR • the actual struct/array/primitive
* • * is a C operator used for 2 purposes: • To declare a variable as a pointer. Ex: int *myIntPointer; • right now, myIntPointer points to a random address • trying to use before initialization results in a segmentation fault or bus error • To dereference an existing pointer variable. Huh? • means to get what’s at the address the pointer stores
& • A C operator used for getting the address of a variable • This would produce an address similar to what’s stored by a pointer
Think of it this way • When you compile a C program, instructions are added for properly running your program • One thing these instructions do is manipulate declared variables • Every declared variable is stored at a memory location • So the question is what’s there? • for a regular int, just a number • for an int*, a memory address of an int
Example, what output will we get? int num = 5; int *pNum = # num = 7; printf("num = %d\npNum = %d\n", num, *pNum); if (&num == pNum) printf("true\n"); else printf("false\n"); OUTPUT: num = 7 pNum = 7 true
So who cares? • Why do we need pointers? What good are they? • In C, pointers can be used to multiple advantages: • call-by-reference methods • dynamic arrays • dynamic memory allocation using pointer arithmetic • Data at the end of a pointer can be filled in later
Call-by-value • In Java, when you pass an argument to a method, you are actually passing a copy of that argument • this is called call-by-value • Ex: public static void main(String[] args) { int x = 5; junk(x); System.out.println("x is " + x); } public void junk(int argument) { argument++; } OUTPUT: x is 5
C also has call-by-reference • We can pass the adddress of a variable. So? • We can directly change the original variable • Ex: void junk(int cbv, int *cbr); int main() { int x = 5; int y = 6; junk(x, &y); printf("x is %d\ny is %d\n", x, y); } void junk(int cbv, int *cbr) { cbv++; (*cbr)++; } OUTPUT: x is 5 y is 7
Is it still call by value? • Some might say it’s still technically call-by-value • we are passing a copy of the address • So, assigning an address to the pointer would not change the original pointer
What’s the output and why? void junk(int *test); int main() { int x = 5; junk(&x); printf("x is %d\n", x); } void junk(int *test) { int num = 10; test = # } OUTPUT: x is 5
What’s dynamic memory allocation? • In Java when objects are constructed based on decisions made at runtime • In C, when structs and arrays are constructed based on decisions made at runtime • For dynamic structs & arrays, we can use pointers
First things first, what’s a struct? • Like a record in Pascal • A single construct that can store multiple variables • sounds like an object BUT • does not have methods
Declaring a struct type & struct variables • To declare a struct type: struct Point { int x; int y; }; • To declare a struct variable: struct Point p1; • To reference data in a struct, use ‘.’ operator, just like an object: p1.x = 5;
struct Point { int x; int y; }; void changePoint(struct Point p); int main() { struct Point p1; p1.x = 100; p1.y = 200; changePoint(p1); printf("p1.x is %d\np1.y is %d\n", p1.x, p1.y); } void changePoint(struct Point p) { p.x *= 5; p.y *= 4; } OUTPUT: p1.x is 100 p1.y is 200 We just changed p, a copy of p1, but not p1
struct Point { int x; int y; }; void changePoint(struct Point p); int main() { struct Point p1; p1.x = 100; p1.y = 200; changePoint(&p1); printf("p1.x is %d\np1.y is %d\n", p1.x, p1.y); } void changePoint(struct Point *p) { (*p).x *= 5; (*p).y *= 4; } OUTPUT: p1.x is 500 p1.y is 800 We just changed p, and so changed p1
BTW, where is p1 in memory? int main() { struct Point p1; p1.x = 100; p1.y = 200; changePoint(&p1); printf("p1.x is %d\np1.y is %d\n", p1.x, p1.y); } IN THE main method STACK FRAME!
struct Point { int x; int y; }; void changePoint(struct Point p); int main() { struct Point *p1 = makePoint(); printf("p1.x is %d\np1.y is %d\n", (*p1).x, (*p1).y); } struct Point* makePoint() { struct Point p1; p1.x = 100; p2.y = 200; return &p1; } What happens? DISASTER! WHY? When makePoint ends, p1 gets popped from the stack
How can we fix this? • Declare a struct pointer variable • When you want to make one on the heap, use malloc • What’s malloc? • a method for dynamic memory allocation • you give it a size • it gives you that many bytes of continuous memory cells • it returns you the address of the first byte in the block
Note, always free what you malloc • C has no garbage collector • If you malloc something, when you’re done with it you need to free it • Why? • if you don’t the memory will not be recycled • this is called a memory leak • Who cares? • you should if you want your program to run efficiently • What’s free? • a method that releases the memory block argument
struct Point { int x; int y; }; void changePoint(struct Point p); int main() { struct Point *p1 = makePoint(); printf("p1.x is %d\np1.y is %d\n", p1->x, p1->y); } struct Point* makePoint() { struct Point *p1; p1 = malloc(sizeof(struct Point)); (*p1).x = 100; (*p2).y = 200; return p1; } NOW IT WORKS
-> • Used to dereference data in a pointer to a struct or array. Ex: struct Point { int x; int y; }; int main() { int pointBytes = sizeof(struct Point); struct Point *p = malloc(pointBytes); p->x = 10; p->y = 20; printf("x is %d\ny is %d\n", p->x, p->y); free(p); }
What if we don’t free? struct Point *p; int pointSize = sizeof(struct Point); int i; for (i = 0; i < 10000; i++) { p = malloc(pointSize); p->x = i % 1000; p->y = i % 500; printf("p->x is %d\tp->y is %d\n", p->x, p->y); } Memory Leak! (that’s a bad thing) • note, by the time this loop ends, your program will be using up 8 bytes * 10000 = 80000 bytes of memory for one p variable • where’d I get 8 bytes from?
What if we don’t free? struct Point *p; int pointSize = sizeof(struct Point); int i; for (i = 0; i < 10000; i++) { p = malloc(pointSize); p->x = i % 1000; p->y = i % 500; printf("p->x is %d\tp->y is %d\n", p->x, p->y); free(p); } No memory leak now What if we were to use p->x now? dangling reference (that’s bad) it might still be there, it might not (segmentation fault error possible)
We can dynamically construct arrays too • With malloc, we can request continuous blocks of memory right? • So a * will point to the front of the block • That can be the first index in an array • What can we put into arrays? • primitives • pointers to primitives (other arrays of primitives) • structs • pointers to structs
char* as an array char *text; text = malloc(sizeof(char) * 4); int i; for (i = 0; i < 3; i++) text[i] = (char)(65 + i); text[3] = '\0'; printf("text is %s\n", text); Output: text is ABC
Pointers to Pointers (for 2D arrays) char **text2; text2 = malloc(sizeof(char*) * 2); text2[0] = malloc(sizeof(char) * 4); for(i = 0; i < 3; i++) text2[0][i] = (char)(i + 65); text2[0][3] = '\0'; printf("text2[0] is %s\n", text2[0]); text2[1] = malloc(sizeof(char) * 6); for(i = 0; i < 5; i++) text2[1][i] = (char)(i + 68); text2[0][5] = '\0'; printf("text2[1] is %s\n", text2[1]);
Array of structs struct Point *points; int numPoints = 5; points = malloc(sizeof(struct Point) * numPoints); int i; srand(time(NULL)); for (i = 0; i < numPoints; i++) { points[i].x = rand() % 1000; points[i].y = rand() % 1000; printf("points[%d] = (%d,%d)\n", i, points[i].x, points[i].y); } bash-2.05$ ./StructArraysTester points[0] = (597,209) points[1] = (41,800) points[2] = (464,96) points[3] = (59,892) points[4] = (418,231)