Signals, Instruments, and Systems W2 C Programming (continued)
C
Main differences with Java C is NOT object oriented. (C++ is OO) C code is directly translated into binary that can be directly executed by the machine. Java is an interpreted language (Bytecode) With C, the programmer can directly access machine resources (memory, processes). In Java, code is executed within a Virtual Machine (safe)
Main differences with Matlab Matlab is an interpreted language Interpreted: The code is transformed into machine executable code at run-time Matlab is optimized for matrix operations Syntax differences (loops, functions, etc ) No variable declarations
How to use it? file.c? file source file executable (binary)
How to use it? gcc file.c o file file.c object file file.o file source file libc executable standard C library gcc is a program, and stands for Gnu C Compiler It contains all standard libraries
Libraries Libraries provide special functionality in the form of collections of ready-made functions: Library: Example: stdio.h printf(const char* format, ) math.h sqrt(double x) time.h gettimeofday() stdlib.h rand() Usage: #include <stdlib.h> #include my_library.h :a collection of function declarations
Main source file Compilation 3 main.c main.o gcc help.o file.o main.c o program -lm Complementary file 1 help.c epc help.o epo program gcc c help.c o help.o Complementary file 2 file.c file.o libc libm gcc c file.c o file.o standard C library math library
Makefile: Example (see previous slide) CC = gcc LDFLAGS = -lm all: main - compiler -additional library - targets main: main.o help.o file.o - label clean: rm rf *.o main -[TAB]!! Note: Run make clean all for a totally new compilation
Example: Hello World In Java class myclass { public static void main(string args[]) { System.out.println("Hello World!"); #include <stdio.h> In C int main(int argc, char *args[]) { printf( Hello World! ); return 0;
Example: Hello World int main(int argc, char *args[]) That is the entry function of any C code. This function is called first when the program gets executed. #include <stdio.h> printf( Hello World! ); This function is in the libc. return 0; It is declared in the stdio.h file. return 0; main always returns an int (integer value). The convention is to return 0 when everything went ok. #include <stdio.h> Includes the declaration of printf in our C code. int main(int argc, char *args[]) { printf( Hello World! );
Variables Just like Java there are several types of variables: Integers: char, short, int, long Floating point: float, double Characters: char There is no Boolean type. Variables can be either signed or unsigned: e.g. unsigned int, signed char
Variables Variables need to be declared before they are used. In correct ANSI C89, variables need to be declared at the beginning of a block (after { ). int main() { int a = 5; double b = 4.3; return (int)((double)a * b); Remark: A variable type can be modified with a cast.
Variables - Cast The cast operator is an operator which forces a particular type mould or type cast onto a value: char ch = a ; int i; i = (int)ch; int i = 1; int j = 3; double k; k = i/j; int i = 1; int j = 3; double k; k = (double)i/ (double)j; i = 97 k = 0 k = 0.3333 careful!
Variables - enum Enumeration of tags. The tags are numbered (0,1,..) (,,) by default. Def.: enum identifier { enumerator-list Ex.: enum BOOLEAN { false, // =0 true ; // =1 enum BOOLEAN is_empty = false;
Variables - typedef Typedef allows you to define your own types. Def.: typedef type typedef-name Ex.: typedef int BOOLEAN; BOOLEAN is_empty = 0;
Operators - Logical Operator e1 < e2 e1 <= e2 e1 > e2 e1 >= e2 e1 == e2 e1!= e2 e1 && e2 e1 e2 Meaning less than less than or equal greater than greater than or equal equal to not equal to logical AND logical OR
Operators - Shortcuts Operator e1 *= e2 e1 /= e2 e1 += e2 e1 -= e2 e1 %= e2 Meaning multiplication division addition subtraction modulo Note: a+= 1 is the same as a++
Operators - Bitwise Operator e1 << e2 e1 >> e2 e1 e2 e1 & e2 e1 ^ e2 Meaning left shift right shift bitwise OR bitwise AND exclusive OR Question: Hint: 20 << 2 =? 10100 << 2 = 1010000 20 >> 2 =? Note: Bitwise calculus is used in advanced code (compression, encryption, or optimizations) and also in embedded systems
Controlling the execution flow Algorithms are all about controlling the execution flow. Algorithms are all about deciding how to proceed depending on some conditional statements. What are the tools we use to do this?
if Def.: Ex.: if (condition) { code; else if (another condition) { another code; else { yet another code; if (a >= b && a!= c) { a = b; else if (a == 3 b == 3) { a = c; else { b = 2*a;
while Def.: while (condition) { code; do { code; while (condition); At any time, you can quit the loop with the keyword break. You can also skip the rest of the code in the loop with continue.
for Df Def.: for (initialization; iti condition; increment) { code; Ex.: for (i = 0; i < i_max; i++) { a = a + i * a; printf( a is equal to: %d \n, a); continue and break can also be used.
switch Def.: switch (expression) { case constant1: break; statements; case constant2: break; statements; Ex.: switch (state) { case SLEEP: sleep_time++; break; case AWAKE: awake_time++; break; default: other_state_time++; default: statements;
stdin - stdout Standard input and standard output are file streams printf( Hello ) is equivalent to fprintf(stdout, Hello ) scanf( %d, &i) is equivalent to fscanf(stdin, %d, &i) stderr is useful to display errors, because it is not affected by redirection (>):./my_program > out.txt -- the errors will still be displayed! KEYBOARD stdin PROGRAM DISPLAY stdout / stderr
Printing Format Most commonly used: %d integer %u unsigned integer %f double %s string %c char Object Control spec. Actual output 42 %6d 42 z %3c z 2.71828 %10f 2.71828 2.71828 %10.2 2.71 printf %s printf
Functions Repetition: If part of the code needs to be repeated several times (more than one), create a function! Structure: If part of the code seems like a subtask of your complete code, create a function!
Why? int main() { matrix A = creatematrix(3,3); A[0][2] = 2.0; printmatrix(a); destroymatrix(a); return 0; = int main() { int i, j; double **A = malloc(3*sizeof(double *)); for (i = 0; i < 3; i++) { A[i] = malloc(3*sizeof(double *)); A[0][2] = 2.0; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { printf( %.2f, A[i][j]); printf( \n ); for (i = 0; i < 3; i++) { free(a[i]); free(a); return 0;
Functions: how? Functions output a type Functions can also take inputs. type name(type1 arg1, type2 arg2, ); Examples: int main(int argc, char *args[]); double cos(double angle); void my_function();
Functions Before using a function, it has to be declared. Unlike Java, C can only back reference: #include <stdio.h> int main(int argc, char *args[]) { print _ hello_ world(); return 0; void print_hello_world() _ { printf( Hello World! ); #include <stdio.h> void print_hello_world() { printf( Hello World! ); int main(int argc, char *args[]) { print_hello_world(); return 0;
Example: π #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> double compute_pi(int p); int main(int argc, char *args[]) { int precision; double pi; if (argc < 2) { fprintf(stderr, "Usage: %s [precision]\n", args[0]); return -1; 1 include the needed functionalities 2 declare the functions 3 main 4 declare needed variables at the beginning g of the block precision = atoi(args[1]); pi = compute_pi(precision); printf("the final value is %.6f\n 6f\n, pi); printf( The real value is %.6f)\n", M_PI); return 0; 5 call your function 6 return
Example: π double compute_pi(int p) { int i; int inside = 0; double ratio; 6 write the declared function 7 declare variables srand(time(null)); for (i = 0; i < p; i++) { double x = 2.0*(double) (rand() () - RAND_ MAX/2)/(double)RAND/ ) _ MAX; ; double y = 2.0*(double) (rand() - RAND_MAX/2)/(double)RAND_MAX; if (x*x + y*y < 1) inside++; ratio = (double)inside/(double)p; return ratio*4.0; 8 return value
Arrays To declare an array: Def.: type name[size]; e.g. double vector[3]; or double matrix[4][6]; To access: name[index] e.g. vector[1] = 4.5; or double a = matrix[0][2]; Remark: indices start at 0 (not 1 like Matlab).
Example: Arrays int main() { int i, j; double A[3][3]; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { A[i][j] = 0; A[0][2] = 2.0; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { printf( %.2f, A[i][j]); printf( \n ); return 0;
Structures Structures can potentially replace objects (from Java). Just like any other variable a atructure needs to be declared before being used: struct pose { double x; double y; double angle; ; struct pose p; The new structure represents a new variable type.
Structures To declare a variable from a structure: struct struct_ name name; ; e.g. struct pose vehicle_position; To access part of a structure: name.member e.g. vehicle_position.x iti = 3.0; or double a = vehicle_position.angle;
struct vec2 { double x; double y; ; Example: Structures double scalar_prod(struct t vec2 v1, struct t vec2 v2) { return v1.x*v2.x + v1.y*v2.y; int main() { struct vec2 v1, v2; v1.x = 1.0; v1.y = 1.0; v2.x = 0.0; v2.y = 2.0; printf( Scalar product equal to %.2f\n, scalar_prod(v1, v2)); return 0;
Example: Matrices (1) Example of all elements you have seen until now we will create: a minimalist matrix-library a main function that uses it a Makefile that compiles it
Example: Matrices (2) matrix.h #ifndef f _MATRIX_H #define _MATRIX_H #define MAX_ROWS 100 #define MAX_COLS 100 typedef struct { double values[max_rows][max_cols]; unsigned int nrows; unsigned int ncols; matrix_t; matrix_t t transpose(matrix_t t A); matrix_t add(matrix_t A, matrix_t B); void print(matrix_t A); #endif
Example: Matrices (2) matrix.c (1) #include "matrix matrix.h h" #include <stdio.h> matrix_t transpose(matrix_t A) { matrix_t t B; unsigned int i, j; B.nrows = A.ncols; B.ncols = A.nrows; for (i = 0; i < A.nrows; i++) { for (j = 0; j < A.ncols; j++) { // Simply assign columns to rows B.values[j][i] = A.values[i][j]; return B;
Example: Matrices (3) matrix.c (2) matrix_t t add(matrix_t t A, matrix_t t B){ matrix_t C; unsigned int i, j; C.nrows = 0; C.ncols = 0; // Sanity check if (A.nrows!= B.nrows A.ncols!= B.ncols) return C; C.nrows = A.nrows; C.ncols = A.ncols; for (i = 0; i < A.nrows; i++) { for (j = 0; j < A.ncols; j++) { C.values[i][j] = A.values[i][j] + B.values[i][j]; return C;
Example: Matrices (4) matrix.c (3) void print(matrix_t A) { unsigned int i, j; for (i = 0; i < A.nrows; i++) { printf(" "); for (j = 0; j < A.ncols; j++) { printf("%8.2f ", A.values[i][j]); printf(" \n"); return;
Example: Matrices (5) main.c #include <stdio.h> #include "matrix.h" int main(int argc, char *args[]) { matrix_t A, B, C; A.nrows = 2; A.ncols = 2; B.nrows = 2; B.ncols = 2; A.values[0][0] = 1.0; A.values[0][1] = 2.0; A.values[1][0] = 3.0; A.values[1][1] = 4.0; B.values[0][0] = 1.0; B.values[0][1] = 2.0; B.values[1][0] = 3.0; B.values[1][1] = 4.0; printf("a = \n"); print(a); printf("b = \n"); print(b); C = add(a,b); printf("a + B = \n"); print(c); C = add(transpose(a), B); printf("a' + B = \n"); print(c); return 0;
Example: Matrices (6) Makefile CC = gcc all: main main: matrix.o main.o clean: rm -rf *.o main
Example: Matrices (7) stdout A = 1.00 2.00 3.00 4.00 B = 1.00 2.00 3.00 4.00 A + B = 2.00 4.00 6.00 8.00 A' + B = 2.00 5.00 5.00 8.00
Remember man? You can use man to show information about functions in the standard libraries of C: e.g. man printf or man atan2 To type in the terminal!
Conclusion
Summary You have seen almost all basics of C Next week,,you will see the pointers. Pointers are a way to access specific places in the computer memory and are a main element of C programming. C resembles Java in syntax, but not in execution. Matlab is a very useful mathematical tool, but is weak for real-time processing