20180820 ******************************************************* // Lines starting with # are processed by preprocessor // No semi-colon // C is case-sensitive #include // int is the return int main(){ // execution printf("Hello, world!\n"); // sends a message to STDOUT // \n \t // \\ \" // 'h' return 0; // 0 for success } Java: javac JVM x.java ------------> X.class ---------> output Perl/python: perl/python x.py / x.py -------------> output C: gcc x.c -----------------> a.out compiled GCC Compile --------------------------------- Two-stage Compilation ---------------------- 1) pre-processing & compiling: gcc -c hello.c (produce hello.o) 2) link: gcc -o hello hello.o Linking several modules example: gcc -c a.c (produce a.o) gcc -c b.c (produce b.o) gcc -o solveWorldHunger a.o b.o Using math library: gcc calc.c -o calc -lm gcc flags --------------------------------- -c compile single module -o output file for object or executable -Wall display all warnings -g insert debugging code -p insert profiling code -l file library -L dir library path -I dir include path C Preprocessor (cpp) --------------------------------- Macro-processor Changes the code gcc -E shows the output of the preprocessor #define ----------- #define name const-expression #define name(param1[,param2[,...]]) const-expression #undef name Example: #define MAXVALUE 100 if( i < MAXVALUE ){ ... } becomes if( i < 100 ){ ... } Can take arguments: #define CHECK(x) ((x) < MAXVALUE) #if #else #endif ----------- #if expression code segment 1 #else code segment 2 #endif Example: #define OS linux #if OS == linux #include #else #include #endif #ifdef / #ifndef ----------- #ifdef name code segment 1 #else code segment 2 #endif Example: DEBUG #include ----------- #include // looks in the include directories #include "filename.h" // Looks in the current directory (first) Include Guards ----------- Example: includeGuardsExample/main-noIncludeGuards.c Comments ********************************* 1) Sections (maybe multi-line): /* any text until */ /* any text until */ 2) Rest of line: // C++-style (can be used in C) 20180827 ####################################################### Numeric Data Types ********************************* type bytes range ----- ----- ------ char 1 -128 to 127 (-2^7 to 2^7) int 4 -2.1 billion to 2.1 billion (-2^31 to 2^31) long long 8 -2^63 to 2^63 float 4 3.4E+/-38 (7 digits of precision) double 8 1.7E+/-308 (15 digits of precision) unsigned Example: unsigned int = 0; Missing? Boolean Strings (Wait for C-style strings) Most Common: ~~~~~~~~~~~~~~~~~~~~~~ char int double 20180829 ####################################################### Variables (Data objects) --------------------------------- Uninitialized variables have "random" value Always initialize your variables Every variable in C has: 1) a name 2) a data type 3) an address (memory location) 4) visibility (which parts of the program can refer to it) 5) lifetime (period during which it exists) Size of an object [think variable for now] is determined when it's created: 1) global data objects at compile time (data section) 2) local data objects at run-time (on the stack) 3) dynamic data objects by programmer (in the heap) Scoping ---------------------- Variables declared in a { } block are usable (visible) only with in that block Variables declared outside of a { } block are global. Use sparingly and with caution Example: variablesExample.c.html Exercise: What will the output be of the following (if any)? int solution; solution++; printf("solution: %d\n", solution); Type Conversion --------------------------------- Explicit Type Conversion: ---------------------- Syntax: (type) Example: int count = 99; double cost = (double) count * 5.34; Example: explicitTypeConversionExample.c.html Implicit Type Conversion: ---------------------- Syntax: Exercise: Discuss with your neighbor what will the output be of the following (if any)? int i = 100000; char c; c = i; printf("i: %d, c: %d\n", i, c); Output: Funky Types are "promoted": char -> int -> long ... If one operand is double, the other is promoted to be a double If either is float, the other is promoted to be a float Exercise: What is the value of the following expressions: int age; A. age = 8 if( age = 8 ){ -> if( 8 ){ B. -age C. 5 + 8 D. 5 / 8 E. 5 / 8.0 F. float( 7/3 ) G. float( 7 ) / 3 Arrays --------------------------------- Examples: ----------- int vec[100]; // holds 100 elements, indexed 0..99 char str[30]; // holds 30 elements, indexed 0..29 float m[12][31]; // holds 12*31 elements vec[55] printf( "%d\n", vec[ 999999 ]); printf( "%d\n", vec[ 101 ]); 20180831 ******************************************************* sizeof( ) ---------------------- sizeof( data type ) returns the number of bytes for a data type Example: ----------- sizeof( int ) or sizeof int sizeof( variableName) returns the number of bytes for variableName Example: ----------- char simpleChar = '!'; sizeof( simpleChar); // or sizeof simpleChar; int vec[100]; sizeof( vec ); int arraySize = sizeof( vec ); int elementSize = sizeof( vec[0] ); printf( "vec has %d elements\n", arraySize / elementSize )); Exercise: Write code to sum the first 50 elements of an int array named receiptTotals. int receiptTotals[ ARRAY_SIZE ]; int sum = 0; for( int i = 0; i < ARRAY_SIZE; i++){ sum += receiptTotals[i]; } Pointers --------------------------------- Review ~~~~~~~~~~~~~~~~~~~~~~ int counter = 1; Pointers are a data type Pointers hold a memory address Example: ----------- int* myIntPtr; double* ptrToGradient; pointers: "variables that tell you where to find something else" (Dale & Weems) Analogy: PO Boxes int secretBankAccountNumber = 456789; int* myIntPtr = secretBankAccountNumber; // bad idea & operator ---------------------- & (address-of operator): returns the memory address of the first byte in memory of a variable myIntPtr = &secretBankAccountNumber; Example: int answer = 42; int* answerPtr = &answer; printf("answer's value: %d\n", answer); printf("answerPtr's value (base-10): %ld\n", (long) answerPtr); printf("answerPtr's value (hexadecimal): %p\n", answerPtr); Memory Contents Type Name Address ------------------ ---- ---------- --------- | | +----------------+ | 0x7ffee348d2e8 | int* answerPtr 0x7ffee348d2e0 +----------------+ | 42 | int answer 0x +----------------+ | | Example: addressOfExample.c (or *.c.html) (left to individual review) * (dereference) operator ---------------------- * dereferences a variable (it interprets the contents of that variable as address, of a particular type_) Allows you to get at the contents of memory, to read or white (use or assign) Example: printf("*answerPtr's value: %d\n", *answerPtr); Example: pointerExample.c (or *.c.html) Exercise: Given the following code, determine the data type for each expression: int x; int* ptr; Expression Data type Possible Values ---------- --------- --------------- x int whole numbers <= +/-2^31 ptr int* a memory location *ptr int &ptr int** a memory location (to a memory location) &x int* a memory location 20180905 ####################################################### Example: +------+ | ???? | 0x10 | | +------+ | ???? | 0x14 | | +------+ | ???? | 0x18 | | +------+ int x; // at 0x10 int* p; // at 0x14 int* q; // at 0x18 +------+ | ???? | 0x10 | | int x +------+ | ???? | 0x14 | | int* p +------+ | ???? | 0x18 | | int* q +------+ p = &x; +------+ | ???? | 0x10 | | int x +------+ | 0x10 | 0x14 | | int* p +------+ | ???? | 0x18 | | int* q +------+ *p = 7; +------+ | 7 | 0x10 | | int x +------+ | 0x10 | 0x14 | | int* p +------+ | ???? | 0x18 | | int* q +------+ q = &p; +------+ | 7 | 0x10 | | int x +------+ | 0x10 | 0x14 | | int* p +------+ | 0x14 | 0x18 | | int* q +------+ q = p; +------+ | 7 | 0x10 | | int x +------+ | 0x10 | 0x14 | | int* p +------+ | 0x10 | 0x18 | | int* q +------+ *q = 11; +------+ | 11 | 0x10 | | int x +------+ | 0x10 | 0x14 | | int* p +------+ | 0x10 | 0x18 | | int* q +------+ p = NULL; +------+ | 11 | 0x10 | | int x +------+ | NULL | 0x14 | (0) | int* p +------+ | 0x10 | 0x18 | | int* q +------+ Exercise: Diagram the elements on the stack and write the output of the following (adapted from HERE): #include int main (){ int numbers[5]; int * p; p = numbers; *p = 10; p++; *p = 20; p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50; for( int n = 0; n < 5; n++){ printf("%d, ", numbers[n]); } return 0; } Exercise: Write code for each of the following and make sure that it compiles: a. Declare ex0 as a pointer to a char b. Declare ex1 as a pointer to a pointer to a char c. Declare ex2 as an array of 10 elements d. Declare ex3 as an array of 10 elements that are pointers to chars e. Declare ex4 as a pointer to an array of 30 char elements f. Declare ex5 as an array of 10 pointers to arrays of 500 char elements g. Declare ex7 as a pointer to const int h. Write a function ex8 that takes a char pointer named pc, increments the address that it points to and returns that value i. Write a function ex9 that takes an int pointer named num, and prints out what num points to and a message saying if what num points to is odd or even C-style Strings --------------------------------- https://i.imgur.com/JdXxHqH.jpg (Portrait: https://i.imgur.com/NwNPU.png (or https://imgur.com/NwNPU)) Examples: cStyleStrings.c 20180907 ******************************************************* Executing a C program: Command-line arguments ---------------------- // Function parameters: // argc: number of arguments // argv: array (notice the []) of char *s (which are pointers to strings) int main( int argc, char *argv[] ){ // ... return 0; } Command-line Example ----------- Syntax: [] Example: a.out 1 23 awesome argc: 4 argv: +---+---+---+---+ | | | | | | | | | | | | | | +-+-+-+-+-+-+-+-+ | | | | | | | v | | v "awesome" | v "23" v "1" "a.out" Libraries --------------------------------- stdio.h I/O string.h character strings ctype.h character types math.h numerical math functions stdlib.h C Standard General Utilities Library (ex atof(), malloc(), NULL, rand(), exit(), etc.) Memory Allocation ********************************* 1) 2) A program's memory footprint: +--------------+ | Headers | +--------------+ | | | Heap | dynamically allocated memory | | +--------------+ | | grows down | | v | | ^ | | grows up | | +--------------+ | | | Stack | "normal" variables & function calls | | +--------------+ malloc() ~~~~~~~~~~~~~~~~~~~~~~ #include Function prototype: void* malloc( size_t size ); Lifetime of the block is until the memory is freed, with free(). free() ~~~~~~~~~~~~~~~~~~~~~~ #include Function prototype: void free( void *ptr ); Memory leak – Example: memoryAllocationExample.c (or memoryAllocationExample.c.html) Other function prototypes in stdlib.h: void* calloc( size_t n, size elementSize); // allocates memory and initializes it to 0 void* realloc( void* ptr, size_t size); // Returns pointer to larger or smaller memory block of size bytes Exercise: pointersExercise-01.c Add code as directed by the comments to pointersExercise.c and execute to see values update: 20180910 ******************************************************* Control structures --------------------------------- grouping: {...} Same as Java if statements ---------------------- Same as Java Syntax: if( condition1 ){ statements1 } else if( condition2 ){ statements2 } else if( condition3 ){ statements3 }else{ statementsN } Be careful when omitting { }s: Example: ifExample.c (or ifExample.c.html) #include int main(){ int x = 7, y = 42; if( x > 0 ) printf("x > 0!\n"); if( y > 0 ) printf("x and y > 0!"); return 0; } switch Statements ---------------------- Syntax: switch( expression ){ case const1: statements1; break; case const2: statements2; break; ... default: statementsN; // optional } Loops ---------------------- while( condition ){ ... } Loop body executes 0 or more times, while condition is != 0 do{ ... } while( condition ); Loop body executes 1 or more times, while condition is != 0 for( init; condition; update){ ... } init is executed once Loop body executes 0 or more times, while condition is != 0 update is executed after every loop body Beware: int n = 0; ... if( n = 42 ){ printf("Something is very, very wrong\n"); } Structured data objects ********************************* structs ~~~~~~~~~~~~~~~~~~~~~~ A developer-defined data type that is a collection of other data types Access members of the struct using the member of operator, "." Syntax: structVariable.field Example: structsExample1.c (or structsExample1.c.html) Example: structsExample2.c (or structsExample2.c.html) Example: structsExample3.c (or structsExample3.c.html) Example with pointers: structsAndPointersExample.c (or structsAndPointersExample.c.html) Functions ********************************* Function Prototypes ~~~~~~~~~~~~~~~~~~~~~~ A function prototype specifies the return type, name and the argument list A prototype is needed if a call to the function appears before the definition of the function Often found in header (.h) files We can pass arguments to functions 1) By value (e.g., int, double) 2) By reference (e.g., int*, double*, struct joeysStruct*) We can return values from functions 1) By value (e.g., int, double) 2) By reference (e.g., int*, double*, struct joeysStruct*) Don't return addresses that are on the stack (in the function) 20180912 ******************************************************* const arguments ----------- Example: void exFunc( const char* str, const int x) { printf("x = %d\n", x); str[5] = "!"; // error: read-only variable is not assignable } Note: C does NOT support overloading functions (although C++ does) Example: overloadedFunctions.c I/O ================================= Formatted strings: Example: printf("%d", age); c - character d - integer f - floating-point number (float) s - C-style string p - pointer (hexadecimal) ld - long int lf - long floating-point number (double) printf() - display to stdout (defaults to the terminal) scanf() - reads from stdin (defaults to the keyboard) Example: ----------- madlibs-main.c madlibs.h madlibs.c Other library functions: ----------- sscanf() - scans a C-style string asprintf() - formats a string (and allocates just enough memory for it) File I/O ================================= The stdio library (stdio.h) has types and functions for file streams File stream type: FILE* Input files: fopen() fscanf() or getline() or fgets() fclose() Output files: fopen() fprintf() fclose() Example: fileIOExample.c scanf Example: processStockData.c