COMP 40: Machine Structure and Assembly Language Programming (Fall 2017) A Quick Look at C for C++ Programmers Noah Mendelsohn (with updates by Mark Sheldon) Tufts University Email: noah@cs.tufts.edu Web: http://www.cs.tufts.edu/~noah
Let s look at some code
Hello world compared #include <iostream> #include <string> using namespace std; string world = "world"; cout << "Hello " << world << endl; #include <stdlib.h> char *world = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; C++ C 3
Hello world compared No namespaces in C #include <iostream> #include <string> using namespace std; string world = "world"; cout << "Hello " << world << endl; #include <stdlib.h> char *world = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; C++ C 4
Hello world compared C++: stream I/O w/cout C: stdio with stdout, printf, etc. #include <iostream> #include <string> using namespace std; int main(int argc, char *argv[]) string world = "world"; cout << "Hello " << world << endl; #include <stdlib.h> char *world = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; C++ C 5
Hello world compared Format string allows substitution #include <iostream> #include <string> #include <stdlib.h> using namespace std; string world = "world"; cout << "Hello " << world << endl; char *world = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; C++ C 6
Format strings: Hello world compared %s string %d integer (decimal, signed) %u integer (decimal, unsigned) #include <iostream> %ld integer (decimal, long) #include <string> #include <stdlib.h> %x integer (base 16 hex) using %c namespace single std; ASCII character %5d integer (5 chars wide) int %-10s string (10 chars left justified) char *world = "world"; main(int Etc, etc. argc, char *argv[]) printf("hello %s\n", world); string world = "world"; return EXIT_SUCCESS; cout << "Hello " << world << endl; C++ C 7
Hello world compared #include <iostream> #include <string> using namespace std; string world = "world"; cout << "Hello " << world << endl; \n = new line char \t = tab char \\ = \ char Etc. #include <stdlib.h> char *world = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; C++ C 8
Basic Datatypes
C and C++ mostly share basic data types char int short int long int long long int float double a single byte, capable of holding one character in the local character set. an integer, typically reflecting the natural size of integers on the host machine. an integer, possibly smaller than int an integer, possibly longer than int an integer, possibly longer than long single-precision floating point. double-precision floating point. Abbreviations: short is same as short int ; long same as long int Examples: int x; short int s; short s; double gpa; 10
Pointers char c; /* a single byte character */ char *cp; /* a pointer to a single byte character */ A pointer variable holds a reference to some other variable. 11
What does this code do? int x; int y; int z; int *ip; variable x holds an integer variable y holds an integer variable z holds an integer variable ip holds pointer to an integer x = 2; y = 3; ip = &z; *ip = x + y; printf( First answer is %d\n, z); If you re not sure, try this code yourself. Try changing it! 12
What does this code do? int x; int y; int z; int *ip; variable x holds an integer variable y holds an integer variable z holds an integer variable ip holds pointer to an integer x = 2; y = 3; ip = &z; *ip = x + y; printf( First answer is %d\n, z); *ip = *ip + z; printf( Seconed answer is %d\n, z); If you re not sure, try this code yourself. Try changing it! 13
More about C Strings
C characters #include <stdlib.h> (void)argc; (void)argv; Printing each one twice in different formats! unsigned char var1 = 'N'; unsigned char var2 = 'O'; unsigned char var3 = 'A'; unsigned char var4 = 'H'; /* %c prints as character %u prints unsigned integer */ printf("the number for %c is %u\n", var1, var1); printf("the number for %c is %u\n", var2, var2); printf("the number for %c is %u\n", var3, var3); printf("the number for %c is %u\n", var4, var4); exit(exit_success); 15
C characters #include <stdlib.h> (void)argc; (void)argv; unsigned char var1 = 'N'; unsigned char var2 = 'O'; unsigned char var3 = 'A'; unsigned char var4 = 'H'; This program prints: The number for N is 78 The number for O is 79 The number for A is 65 The number for H is 72 /* %c prints as character %u prints unsigned integer */ printf("the number for %c is %u\n", var1, var1); printf("the number for %c is %u\n", var2, var2); printf("the number for %c is %u\n", var3, var3); printf("the number for %c is %u\n", var4, var4); exit(exit_success); 16
C characters are integers! #include <stdlib.h> Interesting Characters are also numbers! (void)argc; (void)argv; unsigned char var1 = 'N'; unsigned char var2 = 'O'; unsigned char var3 = 'A'; unsigned char var4 = 'H'; This program prints: The number for N is 78 The number for O is 79 The number for A is 65 The number for H is 72 /* %c prints as character %u prints unsigned integer */ printf("the number for %c is %u\n", var1, var1); printf("the number for %c is %u\n", var2, var2); printf("the number for %c is %u\n", var3, var3); printf("the number for %c is %u\n", var4, var4); exit(exit_success); 17
Hello world compared C: arrays of characters #include <iostream> #include <string> using namespace std; int main(int argc, char *argv[]) string world = "world"; cout << "Hello " << world << endl; int main(int argc, char *argv[]) char *world = "world"; printf("hello %s\n", world); return 0; C++ C C++: string type 18
Our first hello world Huh? How come this is a pointer? C: arrays of characters int main(int argc, char *argv[]) char *world = "world"; printf("hello %s\n", world); return 0; In many cases, a reference to a C array turns into a pointer to the first element using pointers to represent arrays is very common in C. Read about this in K&R! 19
Our first hello world #inlcude <stdlib.h> String literal gives array of characters char world[] = "world"; printf("hello %s\n", world); return EXIT_SUCCESS; 20
C arrays addressed by pointer to first element These do almost the same thing int main(int argc, char *argv[]) char *world = "world"; char universe[] = universe ; printf("hello %s\n", world); printf("hello %s\n", universe); return 0; The relationship between arrays and pointers is subtle & important! This one you need to research using K&R or Harbison & Steele 21
A trickier hello #include <stdlib.h> #include <string.h> char world[] = "world"; printf("hello %s\n", world); world[1] = '\0'; printf("hello %s your string is %d bytes long!\n", world, strlen(world)); return EXIT_SUCCESS; What does this print? 22
If you understand this, you re well on your way! #include <stdlib.h> #include <string.h> char world[] = "world"; printf("hello %s\n", world); world[1] = '\0'; printf("hello %s your string is %d bytes long!\n", world, strlen(world)); world[3] = 'm'; printf("hello %s your string is %d bytes long!\n", world, strlen(world)); world[1] = 'o'; world[4] = '\0'; printf("hello %s your string is %d bytes long!\n", world, strlen(world)); return EXIT_SUCCESS; What does this print? 23
If you understand this, you re well on your way! #include <stdlib.h> #include <string.h> These examples show that: char *world = "world"; 1) The printf("hello logical length %s\n", of a C world); string is determined by the terminating null world[1] character = \0 '\0'; printf("hello %s your string is %d bytes long!\n", 2) Printing using %s and checking length with strlen() respect this world, strlen(world)); 3) In a correct program, there should be at least enough world[3] = 'm'; space for the string, but you may have allocated more printf("hello %s your string is %d bytes long!\n", 4) In buggy world, programs, strlen(world)); you fail to null terminate or index off the world[1] end of the = 'o'; allocated space world[4] = '\0'; printf("hello %s your string is %d bytes long!\n", world, strlen(world)); return EXIT_SUCCESS; 24
Structured Data
Some structured data #include <stdlib.h> struct student char *name; int age; ; struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; Primitive types mostly the same as C++ unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 26
Some structured data C has structs, not classes #include <stdlib.h> struct student char *name; int age; ; structs have data only no methods! struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 27
Some structured data #include <stdlib.h> struct student char *name; int age; ; struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; unsigned int i; (void)argc; (void)argv; Unlike C++: keyword struct required when naming a structured type for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 28
Some structured data #include <stdlib.h> struct student char *name; int age; ; Initializers more or less the same as C++ struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 29
Some structured data #include <stdlib.h> struct student char *name; int age; ; We can leave out array bound if initializer determines the size same as C++ struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 30
You saw printf and format strings earlier! #include <stdlib.h> struct student char *name; int age; ; struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; You will want to learn about printf and fprintf format specifications unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return EXIT_SUCCESS; 31
Good Practice: Single Point of Truth
Single point of truth int main(int argc, char *argv[]) struct student char *name; int age; ; What s going on here? struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, ; unsigned int i; (void)argc; (void)argv; for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return 0; 33
Single point of truth int main(int argc, char *argv[]) struct student char *name; int age; ; struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, albert", 22, ; What if number of students changes? 34 unsigned int i; (void)argc; (void)argv; for (i=0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; return 0;
Single point of truth #include <stdlib.h> struct student char *name; int age; ; struct student students[ ] = "mary", 15, "bob", 9, "tina", 12, albert", 22, ; unsigned int i; (void)argc; (void)argv; There is a single point of truth for the number of students Try to have single points of truth for anything in your program that s likely to change, or on which multiple other things depend if we change this structure, everything just works! for (i = 0; i < sizeof(students) / sizeof(struct student); i++) printf("student %s is %d years old.\n", students[i].name, students[i].age); ; 35 return EXIT_SUCCESS;
Why we use Hanson in COMP 40
What about abstract data types like list, or table? Many modern languages have them built into the standard Python, Ruby, etc., etc. C++ Standard Template Library (STL) C does not standardize implementation of types like these Hanson gives us C based ADT implementations that: Are useful in our programs Teach us what s going on in many of those higher level language implementations Teach us many good techniques for building modular structures in C 38
C vs C++ File I/O
Access to files and input Feature C C++ Pre-opened streams Open a file Typical use In both languages: stdin, stdout, stderr FILE *fp fopen(filename, r ) fprintf(stderr, error\n ); fprintf(fp, Hi! ); cin, cout, cerr ifstream myfile( filename ); cerr << error << endl; myfile << Hi! ; The operating system pre-opens the three standard streams They can be redirected from the command line: myprog < somefile # stdin reads from somefile myprog > somefile # stdout writes to somefile otherprog myprog # stdin of myprog is output of otherprog 40
Memory allocation
There is no new in C! C++ new allocates and initializes objects: Car *mycar = new Car(V8, Blue); // Create a new car The above allocates space and initializes all the data for mycar delete mycar; Runs destructors and releases memory Also: int *ip = new int[len]; // allocate array delete[] ip; // delete array Also: std:vector // truly dynamic array 42
There is no new in C! C++ new builds objects: Car *mycar = new Car(V8, Blue); // Create a new car The above allocates space and initializes all the data for car delete mycar; Runs destructors and releases memory Also: int *ip = new int[len]; // allocate array delete[] ip; // delete array Also: std:vector // truly dynamic array C malloc/free allocate and free bytes: struct car.members here ; struct car *car_p = malloc(sizeof struct car); allocate unitialized bytes struct car *car_p = malloc(sizeof *carp); Same, but keeps working if structure name changes: single point of truth! You must check the return value to make sure it worked! free(car_p); /* frees the bytes */ 43
There is no new in C! C++ new builds objects: Car *mycar = new Car(V8, Blue); // Create a new car The above allocates space and initializes all the data for car delete mycar; Runs destructors and releases memory Also: int *ip = new int[len]; // allocate array delete[] ip; // delete array Also: std:vector // truly dynamic array C malloc/free allocate and free bytes: struct car.members here ; struct car *car_p = malloc(sizeof struct car); allocate unitialized bytes struct car *car_p = malloc(sizeof *carp); Same, but keeps working if structure name changes: single point of truth! You must check the return value to make sure it worked! free(car_p); /* frees the bytes */ Rule of thumb: The first statement after a call to malloc handles NULL 44
A Bit of History
C++ is an extension to C C was invented many years earlier (c. 1970) C is a quite small language; C++ is much more complicated C is much closer to the hardware, why we re using it! Good programmers know how each C construct compiles No single C expression compiles to huge amounts of code Most of C survives in C++ Primitive data types: int, float, double, etc Control structures (if, while, function call) Source structures (#include and preprocessor) Much more C does not have: Classes, methods, namespaces, dynamic arrays, dynamic strings, IO streams (in the C++ sense), inheritance, built in higher level ADTs (list, vector, deque, table, etc.) 46