340 likes | 465 Views
Overview of programming in C. C is a fast, efficient, flexible programming language Paradigm: C is procedural (like Fortran, Pascal), not object oriented (like C++, Java) C code is compiled, not interpreted (like python, perl, java) higher speed
E N D
Overview of programming in C • C is a fast, efficient, flexible programming language • Paradigm: C is procedural (like Fortran, Pascal), not object oriented (like C++, Java) • C code is compiled, not interpreted (like python, perl, java) higher speed • High degree of memory control (pointers, dynamic allocation), compiled code much faster than mathematica et al. • Very efficient compilers available, very fast and portable • Similar syntax to Java • Together with Fortran most commonly used platform for HPC • All of Unix is written in C!
Basic programming cycle • Write your program in a text editor (for example emacs)/* hello world */#include <stdio.h>int main() { printf("Hello world.\n");return 0;} • Compile: invoke gcc -o hello hello.c on the command line • Run: type hello • Analyse output (gnuplot, etc) • Note: name of compiler may vary: gcc (GNU), icc (intel), cc (Sun), pgcc (portland group)
Structure • Comments appear in /* */ or start with // for one line comment • Each line ends with ; • A C program consists entirely of functions • It must have at least one special function:int main () { variable declarations … function1(); function2(); …}which can call additional functions to perform operations • Functions other than main() must be first declared, then defined:Ex: int function1();
Functions • Example:int multbytwo(int x) { int retval; retval = x * 2; return retval; } • You can declare a prototype int multbytwo(int); before main() and define the function later • Functions of type int or double require a return statement;void returns nothing
A typical program • /* include statements */#include <stdio.h> // basic io-capability#include <math.h> // basic math: exp,sin,cos,…/* function declarations */void initialize(); // read in parameters for simulationvoid compute(int); // perform actual computation void output(); // produce output, write data to fileint main() {initialize();compute(int);output();}/* function definitions */void initialize(){…} • In longer programs, function declarations are moved to "header" (.h) files
Data types • int: integer (4 bytes on 32-bit machines encodes 232 numbers)Ex: int n=100; • float: real number (4 bytes)Ex: float x=0.4502; • double: high (double) precision real number (8 bytes) • char: alphanumerical character (1/2 bytes) • The sizeof() command returns the # of bytes reserved for variable Qualifiers: • const: will not change • long: increase storage (eg long int 64 bit) Note:in C, all variables must be declared in the beginning before any non-declaratory statement; cannot use keywords!
Assignments and arithmetics • Variables must be declared at start of function, same type can be grouped together, can be initialized at declaration:int l,m;m=5;l=10;l=m+l; • double x=5.8,y,z;y=4.6;z=x*x+y*y;z=sin(x); • Casting: change type of variablel=(int)z;z=(double)m/(double)l; //ensures floating point division
Arithmetic operators • Assignment: = • Binary arithmetic: +, -, *, / , % Can be applied to int, float or double except the modulus operator % (int only) • Shortcuts: +=, -=, *=, /=x+=2; // equivalent to x = x+2; x*=2; // equivalent to x = x*2; • Increment/Decrement: ++,--x++; // acts like x = x+1;x--; // acts like x = x-1; • Both x++ and ++x are expressions, but ++x acts like x+1; Example: b=10; c=b++; // c is 10 and b is 11;b=10; c=++b; // c and b are now 11;
Output to screen: printf() • Output to screen: printf("format string", var1, var2, var3); • Format string can be text or % for variables, followed by type%d: integer %ld: long integer %f: float %c: character %s: stringmore general: %length.precision type, eg. %10.8f prints 10 total digits, 8 after the . point\n: newline (cr) \t: tab • Example:int x = 3;int y = 15;char op = '+';printf("\t%d %c %d = %d\n", x, op, y, x + y);Result: 3 + 5 = 18; • Note: input from screen: scanf() (later)
Scope of variables • If declared within a function, the variables are only known to that function (local variable), i.e. within the {} • If declared before main(), the variable is known to all functions and can be manipulated everywhere (global variable)int i,j;// global variablesint main{ double x; // local variable} • Global variables can be used to share information between functions, but this is not recommended/good style • Better: variable pass by value or by pointer in function argument (later)
Flow control • Branching with if … else#include <stdio.h> int main() { int cows = 6; if (cows > 1) printf("We have cows\n"); if (cows > 10) printf("loads of them!\n");} • Format: if (expression) {statement;}else if (expression) {statement;}else {statement;} • Useful operators in logical expression: relational: <, >, <=,>=,equality: ==, inequality: !=logical: and &&, or ||
Loops • while loop (repeating if, condition checked at start):Format: while (expression) {statement;} • for loop (for lists): Format: for (initial-stmt; cond; interation-stmt) {statement;}Ex: for (i=0; i<10; i++) {statement;} • do...while loop (condition checked at end):Format: do {statement;} while (expression); • switch (nested if...else):Format: switch (expression){ case const1 {statement;break;} case const2 {statement;break;} }
Examples • Summation int main() { int i=1, sum=0; for (i=1;i<=10;i++) { sum=sum+i; } printf("The sum is: %d\n",sum);} • Switchswitch (month) { case 1 : case 3 : case 5 : case 7 : case 8 : case 10 : case 12: printf("31 days\n"); break; case 2: printf("28 or 29 days\n"); break; case 4 : case 6 : case 9 : case 11 : printf("30 days\n"); break;}
Pointers • A variable is stored in a certain memory location or address • Pointers allow to manipulate these addresses explicitly • Declaration: add a star to the type you want to point toEx: int *a;declares variable of type int that holds the address (a pointer to) an int • Two operators:- & operator: "address of", can be applied to any variable, result has "one more star"- * operator: "dereference", accesses the object that the pointer points to, can only be applied to pointers, result has "one less star"
Pointer examples • int main() { int i=5,j=2,z=3; //regular variables int *ip; //pointer declaration ip = &i; //pointer now points to location of i j = *ip; //accesses value of object; j now has value 5 *ip = 7; // } • Do not confuse notation:int *a declares the pointer;* operator ("content-of") dereferences ("makes less of a pointer") • Can assign pointer values to other pointers:int *ip2; ip2=ip; // ip2 points to the same location as ip
Why pointers? • Consider swapping two values:void swap(int x, int y){ int temp; temp=x; x=y; y=temp;}int main() { int a=3,b=5; swap(a,b); printf("a is %d, b is %d\n",a,b);} • Result: a is 3, b is 5! What went wrong?C is "pass by value", the called function cannot manipulate the original variables
A correct swap • Cure: pass pointers and not variables:void swap(int *px, int *py){ int temp; temp=*px; *px=*py; *py=temp;}int main() { int a=3,b=5; swap(&a,&b); printf("a is %d, b is %d\n",a,b);} • Pointers are most useful for passing data between functions
Arrays • Often we need to manipulate large vectors or matrices of data • Arrays allow to refer to a number of instances of the same nameEx: int data[5];declares an integer array of length 5 • Note: in C arrays are zero-indexed - numbering begins at zero!! • data[expr] accesses elements of the array where expr evaluates to an integer • Careful: there is no range checking. Only access elements 0 to N-1 for an array of size N. • Multidimensional arrays:int data[N][M][L];
Arrays and Pointers • An integer array a is just a pointer, it is of type (int *). • a points to first memory location of the array.int *ip;ip=&a[0]; // sets ip to point to element zero of a(ip+i) points to the i-th element a[i] and *(ip+i) are equivalent! ip[i] and *(ip+i) are equivalent! • Since an array is a pointer it can be manipulated by a function:Ex: void func (int *a){} int main (){ int b[3]={85,6,7}; func(b); }Note: declare function to accept pointer!
What is the output? • int main(){ int a[4] = { 0, 1, 2, 3}; int *pa; pa = a+1; printf ("%ld\n", *pa); printf ("%ld\n", pa[2]); pa++; printf( "%d\n",pa[0]); scanf("%d", pa+1); printf("You typed: %d\n",a[3]); } 1 3 2 6 You typed: 6
Structured Data Types • The structure mechanism allows to aggregate variables of different types:struct complex { double real; double im;}void func(){ struct complex a,b; a.real=3; a.im=5; b=a;} • "." is the member operator; connects structure and member
File I/O • Use fprintf or fscanf for input/output from/to files • Accessing files requires first the allocation of a file pointer:FILE *results; then opening the file for read/write/append withresults=fopen("data.dat","w"); or "r" or "a" • Write to file (formatted output): fprintf(results, "format string\n", var1, var2, var3); • Read from file (formatted input): fscanf(results, "format string\n", &var1, &var2, &var3); Note: fscanf expects a location for the data, hence the &-operator. • Finally: fclose(results); • Note: standard input/output are handled as files; printf/scanf are just special cases of fprintf/fscanf applied to stout/stdin
Dynamic memory allocation • Often we do not know the amount of required memory at compilation time (eg. variable size problem) • int data[size] is a static array cannot change its size • Need to allocate memory dynamically, "on the fly" • malloc(size): allocates size bytes and returns a pointer to the allocated memory (or new in C++/Java) • free(ptr): frees the memory space pointed to by ptr • Example:#include <stdlib.h>int *data; int length=1000;data = malloc(sizeof(int)*length); //allocates int arrayfree(data);
Dynamic memory allocation • If malloc is unable to allocate memory, it returns NULL pointer; good to check whether malloc was successful:if(ip==NULL) { printf("out of memory\n"); exit(1);} • It is possible to extend allocated memory:datanew = realloc(data, sizeof(int)*(length*2));creates contiguous block in memory; appends to existing data
Multidimensional arrays • To allocate multidimensional arrays, we use pointer to pointers:#include <stdlib.h> int **array; array = malloc(nrows * sizeof(int)); if(array == NULL) { fprintf(stderr, "out of memory\n"); exit(1);} for(i = 0; i < nrows; i++) { array[i] = malloc(ncolumns * sizeof(int)); if(array[i] == NULL) { fprintf(stderr, "out of memory\n"); exit(1);} } • Can access like static array:array[i][j];
Tips for compiling • Compiling has three stages: 1) preprocessing 2) compile to object code (.o) 3) link all pieces and create executable • Compiler options help control the process (see man gcc).All options start with -, some important options are:-o: name of executable-O, -O2: turn on optimizer-I: additional search path for include-files (.h)-c: create only object code, do not link (for larger projects)-l: link library, e.g -lm for link to math library-L: additional search path for library-files-g: produce debugging info (for gdb or ddd)-Wall: turn on all warnings
Preprocessor statements • #include inserts the entire content of a file, verbatim.#include "filename": searches for file in current directory#include <filename>: searches standard paths, typically for standard library header files • #define allows to set up macros#define SIZE 10: the preprocessor replaces all occurrences of SIZE with 10.- Makes global changes easier- Makes programs easier to read • Conditional compilation : #ifdef name … #endifcontrol with -Dname at compilation
Working with libraries • Libraries provide convenient access to additional functions • Ex: sin(x), cos(x), exp(x) are all in the math library • To access these functions, first include the corresponding header file (eg. math.h), then link the library with -lm when compiling • We will use libraries like the GNU scientific library libgsl.a In this case:1) include <gsl/gsl_sf_bessel.h>(in code) 2) gcc prog.c -o prog -lm -lgsl -I/usr/local/lib(on hyper.phas.ubc.ca)Note: each library is searched only once, so the order matters!
Example: random number generator #include <stdio.h> #include <gsl/gsl_rng.h> // include header files int main () { const gsl_rng_type * T; // define pointer to rng typegsl_rng * r; // define pointer to rng double u;gsl_rng_env_setup(); // reads env variables (seed)T = gsl_rng_default; // sets default rng r = gsl_rng_alloc (T); // returns pointer to rng Tu = gsl_rng_uniform (r); // samples from the rngprintf ("%.5f\n", u); } gsl_rng_free (r); // free up memoryreturn 0; }
Other libraries • -lmpich: message passing interface (MPI) for parallel code • -lfftw: fast fourier transforms • -llinpack: linear algebra • -lblas: basic linear algebra • … and many more
The make utility • make is a powerful UNIX tool to manage the development of larger projects • Executables are viewed as targets that have dependencies • A Makefile consists of definitions of one or more targets and how to "make" them • Each target definition contains: 1. name of the target, followed by : 2. list of dependencies 3. set of actions that define how to make the target • Example: prog1: prog1.c gcc -g -O prog1.c -o prog1Note: all lines stating actions MUST begin with a TAB to compile, simply type "make"
Makefiles continued • For portability, make can access environment variables $(HOME) (note syntax) • We can define our own macros:MYLIB = $(HOME)/libCCFLAGS= -g -O -I$(HOME)/include(useful for automating the compilation process) • Note: to continue beyond one line use the \ (continuation construct)FILES= a.c\ b.c\ c.c • One can have generic targets:.c.o: gcc $(CCFLAGS) $.ctells make how to make a .o file from a .c file
A longer Makefile example OBJ= prog1.o CXXFLAGS=-g -O2 -lm -Wall LINKFLAGS=-lm CXX=gcc .c.o: $(CXX) $(CXXFLAGS) -c $*.c prog1: $(OBJ) $(CXX) $(LINKFLAGS) -o $@ $(OBJ) clean: rm -f *.o rm prog1
Data visualization • gnuplot is a simple but powerful plotting tool • Plotting of functions:f(x)=some functionp f(x) • Plotting of data:p "data.dat" using ($1):($2)plots first column of data against second columndata can be processed by functions: eg. log($1):log($2) • Print to file: set term post eps enhanced //switch output to encaps. psset out "plot.eps" //name of output filep "…" // plot commandset term x11 // switch output to screen • Can automate using gnuplot scripts