class: title, smokescreen, shelf, bottom, no-footer background-image: url(images/hello-world.png) # 181U Spring 2020 ### C for Java Programmers --- layout: true .footer[ - Geoffrey Brown, 2020 - 181U ] <style> h1 { border-bottom: 8px solid rgb(32,67,143); border-radius: 2px; width: 90%; } .smokescreen h1 { border-bottom: none; } .small {font-size: 80%} .smaller {font-size: 70%} .small-code.remark-slide-content.compact code {font-size:1.0rem} .very-small-code.remark-slide-content.compact code {font-size:0.9rem} .line-numbers{ /* Set "line-numbers-counter" to 0 */ counter-reset: line-numbers-counter; } .line-numbers .remark-code-line::before { /* Increment "line-numbers-counter" by 1 */ counter-increment: line-numbers-counter; content: counter(line-numbers-counter); text-align: right; width: 20px; border-right: 1px solid #aaa; display: inline-block; margin-right: 10px; padding: 0 5px; } </style> --- class: compact # Agenda * Why C ? * Comparison wth Java * Program structure * Modules * Strings/Arrays --- class:compact # Why C ? * C is the most common language for interfacing to hardware -- designed circa 1970 to implement Unix * C has a tiny default footprint which is important for embedded hardware * C is easily interfaced to assembly language * C pointers provide mechanism to directly communicate with hardware | Java | C | | ---- | --- | | Object-oriented | Procedural | Interpreted | Compiled | Automatic memory management | **Programmer manages memory ** | | References | Pointers | | No hardware access | Direct hardware access | --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Example Program ```c #include <stdio.h> double value; // a comment /* multi-line comment */ int main(void){ int local = 0; value = 0.42; printf("local = %d value = %f\n",local,value); return 0; } ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers,col-2 # Example Program ```c #include <stdio.h> // Included definition double value; // Module variable int main(void){ int local = 0; // Local variable value = 0.42 // printf is a library function printf("local = %d value = %f\n",local,value); return 0; } ``` <br> <br> * '#' is a preprocessor directive * Comments begin with // or are enclosed in /* ... */ * Variables can be local to procedure or at file (module) level --- class: compact # Building and running in vscode ![](images/vscode-example1.png# w-70pct fr) * Build: Terminal->Run Build Task * Run: In terminal, execute ./example1 --- class: compact,col-2 # Built-in types | Type | Java | C | | ---- | ---- | -- | | char | 16 bits | 8 bits | | short | 16 bits | 16 bits | | int | 32 bits | 16,32 , or 64 bits | | long | 64 bits | 32 or 64 bits | | float | 32 bits | 32 bits | | double | 64 bits | 64 bits | | boolean | 1 bit | (use int) | | byte | 8 bits | (use char) | | long long | | 64 bits | C doesn't have boolean. Integer 0, null pointer are false, anything else is true. C types are machine/compiler dependent -- this can cause problems. Where size matters we use * `#include <stdint.h>` * uint8_t, int8_t * uint16_t, int16_t * uint32_t, int32_t * uint64_t, int64_t --- class: compact # C allows us to "hang ourselves" ```c void example(void) { int y; int x = 100; if (x == 4) { } // not taken if (x) { } // taken while (x) { x--; } /* MISTAKES */ if (x = 1) { } // assignment ! // x assigned 1, now it // is taken. Syntax error in Java // but not in C while (y) { y--; } // not initialized // compiler error in Java allowed // in C } ``` --- class: compact,small-code,hljs-tomorrow-night-eighties,line-numbers,small # Variables and scope There are no **classes** in C. The only unit of modularity is the source file (typically *.c ). Variables declared within a file, but outside of any procedures are considered **global** and "live" for the entire program execution. * A variable is declared and, optionally, initialized in a single statement `int some_variable = 42;` * To use a global variable declared in another file, use the **extern** keyword as in `extern int value;` * Constants are declared as `const int size = 42;` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Variables and scope (cont.) * To make a variable *invisible* to other files `static int name;` Note that **static** is very different from Java. * For hardware, we often use the **volatile** keyword which means the variable must not be allocated to a register and must be written back to "memory" when assigned `volatile int important;` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Variables and scope (cont.) **Local Variables** are declared inside of procedures. ```c int bar(){ int x = 4; ... ``` **static**, inside a procedure, defines a variable that is shared and preserved across all invocations of the procedure. ```c int foo() { static int = 3; ... ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # What is a module ? * File is the unit of compilation -- a module is a file * There are no classes * There are no objects * Variables are one of: * global (declared at the module level) * private to module (declared static at module level) * private to procedure (declared in procedure) * dynamic -- created on each invocation * static -- lives for life of program --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers,col-2 # Operators in C and Java are similar | expression | meaning | |:---:| ---:| |`!exp` | logical not | | `exp && exp` | logical and | | ... | other logic | | `exp == exp` | logical equals | | `exp < exp` | logical smaller | | ... | other comparison | | `exp + exp` | addition | | `exp - exp` | subtraction | | ... | other arithemetic | | `exp & exp` | bit-wise and | | `exp ^ exp` | bit-wise or | | ... | other bitwise | | `exp >> exp` | shift right | | `exp << exp` | shift left | | `exp ? exp : exp` | conditional | --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Statements The **if**, **while**, **for**, and **switch** statements in C behave *almost* the same is in Java. * The expressions in the **if**, **while**, and **for** statements do not use boolean values -- any type will do. A value of 0 is evaluated as **false**, any non-zero value is evaluated as **true** ```C for (int i = 10; i; i--) { ... } int x = 42; if (x) { ... } ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Arrays Arrays are *really* different in C. * They don't have a size * Their bounds aren't checked * *Any* variable can be *cast* as an array. ```C int a1[5]; // OK int a2[] = { 1, 2, 3 };// OK (size calculated by compiler) int a5[9]; a5[10] = 7; // Oops !!! C doesn't check bounds a5[1000] = 9; // Oops a5[-5] = 5; // Oops int a3[]; // Error -- size required here a3 = a2; // Error -- can't assign array ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Arrays ```C int [] function(void) int array[5]; return array; // can't return array } void foo(int a[]) { // ok -- can pass array as parameter a[3] = 0; } void bar(void) { int a[5]; // can pass array as a parameter because bar() // has longer life that foo foo(a); } ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers, col-2 # Strings Strings is C are just arrays of type **char** in which the last element is `0` (null-terminated). There are no string "methods" ! ```C char name0[5]; name0[0] = 'J'; name0[1] = 'a'; name0[2] = 'v'; name0[3] = 'a'; name0[4] = 'J'; name0[0] = '\0'; char name1[] = {'J', 'a', 'v', 'a', 0}; ``` The normal ways to initialize strings are somewhat different ```C char name2[5] = "Java"; char name3[] = "Java"; char name4[100] = "Not 100 chars long !"; ``` --- class: small-code,compact,hljs-tomorrow-night-eighties,line-numbers # A little string program ```C int strlength(s) { cnt = 0 for (int i = 0; s[i]; i++) cnt++; return cnt; } // or int strlength(s) { for (int i = 0; s[i]; i++); return i - 1; } ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Structures C **structures** are like Java objects, but without methods ```C struct identifier { type variable_name; type variable_name; ... }; struct identifier variable; ``` ```C struct ComplexNumber{ double real; double imag; } c1, c2; c1.real = 1.0; c1.imag = 0.0; c2.real = 2.0; ... ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Unions Unions are a unique feature of C -- they look like structures, *but*, the fields are allocated to the same memory; modifying one field modifies them all ! They are used extensively for variable formats (e.g. network protocols) as well as for describing hardware. ```C union MyUnion { int i_value; double d_value; }; union MyUnion u; u.i_value = 6; u.d_value = 5.4; // overwrites i_value ! union Value { struct ComplexNumber c1; double values[2]; } u2; u.c1.real = 1.0; // same as values[0] u.c1.imag = 2.0; // same as values[1] ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Defining Types We can define new types in C ```C typedef char byte; byte b = 123; typdef struct ComplexNumber complex; complex v; v.real = 5.9; v.imag = 0.1; ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Functions ```C type identifier(parameter-list) { function-body} ``` ```C int foo(int value, double d) { ... return some_value; } ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Functions We define the function type with a prototype. ```C int max(int, int); // prototype int result; void example(void) { result = max(3,5); } int max(int one, int two) { return one < two ? two : one; } int main(void) { example(); } ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # The main function Every C program has a main function ```C int main(void) {...} int main(int argc, char *argv[]) {...} ``` ```C #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) { printf("%s\n",argv[i]); } return 0; } ``` ```C kinsella:c-programs geobrown$ ./args a b c d ./args a b c d ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers,col-2 # The C Preprocessor C programs make extensive use of a *preprocessor*, which allows the definition of macros and inclusion of other files. It is important to understand, the preprocessor is based upon text-substitution. ```C #define SOME_CONSTANT 42 int x = SOME_CONSTANT; #define MAX(X,y) ((x) > (y) ? (x) : (y)) y = MAX(3,4); ``` **#define** ```C #define identifier replacement-text #define identifier(parameter-list) (replacement-text) #undef identifier ``` ```C #ifdef identifier <code> #else <code> #endif ``` ```C #ifndef identifier <code> #endif ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers,col-2 # The C Preprocessor ```C #define LOOPS 100 /* constant */ #define MAX(A,B) ((A) > (B) ? (A) : (B)) /* macro */ #define DEBUG1 void function(void) { int i,j; #ifdef DEBUG1 print("starting loop\n"); #endif ... return MAX(i,j); } ``` <br> Will be converted to ```C void function(void) { int i,j; ... return i > j ? i : j; } ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers,col-2 # The C Preprocessor -- Including Things A **very** important use of the preprocessor is to include other files. In C, the convention is to create a pair of files (*.c,*.h) for every module. For example: module.c: ```C int a_shared_variable = 0; void foo(void) { return;} ``` module.h: ```C extern int a_shared_variable; void foo(void); ``` The declarations might be imported into a second module module2.c: ```C #include <module.h> void bar(void){ a_shared_variable = 3; } ``` Unlike Java, there is no type enforcement -- the shared declarations in module.h provide a way to communicate *hints* to the compiler. --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # The C Preprocessor -- Including Things Any time you use a library function, you should include the appropriate *header* (.h) file: ```C #include <stdio.h> void function(void) { printf("Hello world\n"); } ``` will be converted by the by the preprocessor to ```C int printf(const char *__format, ...); int sprintf(char *__s, const char *__format,...); ... lots of other definitions ... void function(void) { printf("Hello world\n"); } ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Header Files Any time you want to use resources (variables,functions) defined in one module in another, you should create a corresponding header file. There is an *idiom* for these to protect against multiple inclusion. ```C #ifndef _SOME_FILE_H_ #define _SOME_FILE_H_ struct ComplexNumber { double real, imag; }; typedef struct ComplexNumber complex; complex c_create(complex c1, complex c2); complex c_add(complex c1, complex c2); #endif ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Some Standard Libraries * **stdio.h** : Input/output functions * **stdlib.h** : Standard functions and macros * **stddef.h** : Standard definitions * **math.h** : Math functions * **string.h** : String functions * **time.h** : Time functions --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # printf **printf**, which is part of **stdio.h** provides a way to format and print strings. The model is a bit unusual. A format string, with "placeholders" defines what is to be printed; a variable-length list of arguments provides the values to be formated. ```C int printf(const char *format,...); ``` ```C printf("Hello world\n"); // hello world int val = 5 printf("Hello %d world\n", value); // Hello 5 world char c = 'a'; printf("val = %d c = %c\n",value,c); // val = 5 c = a ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # printf formats | format | type | |:--:|--| | **%d** | signed int | | **%u** | unsigned int | | **%x** | hexadecimal | | **%f** | double and float | | **%s** | string | | **%.2f** | float or double with two decimal places | And many more options to control width and type of placeholders. --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Getting Help `man -S section subject` ``` man -S 3 printf PRINTF(3) BSD Library Functions Manual PRINTF(3) NAME printf, fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf, vasprintf, vdprintf -- formatted output conversion LIBRARY Standard C Library (libc, -lc) SYNOPSIS #include <stdio.h> int printf(const char * restrict format, ...); int fprintf(FILE * restrict stream, const char * restrict format, ...); ``` --- class: very-small-code,compact,hljs-tomorrow-night-eighties,line-numbers # Compiling ``` gcc -o myprogram myprogram.c ``` This performs the following steps: 1. *preprocessing* -- expand macro definitions in `myprogram.c` 2. *compiling* -- compile the output of the preprocessor to `myprogram.o` 3. *linking* -- "link" `myprogram.o` with libraries and produce an executable `myprogram` Building a program with multiple modules, we can postpone the linking step to the end. ``` gcc -c file1.c gcc -c file2.c gcc file1.o file2.o -o myprogram ``` --- class: compact # Java vs C Environments ![](images/java-environment.png# w-40pct) ![](images/space.png# w-2-12th) ![](images/c-environment.png# w-40pct) Images from https://www.cs.rochester.edu/u/ferguson/csc/c/c-for-java-programmers.pdf --- class: compact # Summary * These slides derived from * https://www.cs.utexas.edu/~ans/classes/cs439/docs/dictaat.pdf * Other sources of information: * https://www.cs.rochester.edu/u/ferguson/csc/c/c-for-java-programmers.pdf