590 likes | 746 Views
Week 5 - Monday. CS222. Last time. What did we talk about last time? Processes Lab 4. Questions?. Project 2 . Quotes. A C program is like a fast dance on a newly waxed dance floor by people carrying razors. Waldi Ravens. Arrays. Declaration of an array.
E N D
Week 5 - Monday CS222
Last time • What did we talk about last time? • Processes • Lab 4
Quotes A C program is like a fast dance on a newly waxed dance floor by people carrying razors. WaldiRavens
Declaration of an array • To declare an array of a specified type with a given nameand a given size: • Example with a list of type int: type name[ size ]; int list[ 100 ];
Differences from Java • When you declare an array, you are creating the whole array • There is no second instantiation step • It is possible to create dynamic arrays using pointers and malloc(), but we haven't talked about it yet • You must give a fixed size (literal integer or a #define constant) for the array • These arrays sit on the stack in C • Creating them is fast, but inflexible • You have to guess the maximum amount of space you'll need ahead of time
Accessing elements of an array • You can access an element of an array by indexing into it, using square brackets and a number • Once you have indexed into an array, that variable behaves exactly like any other variable of that type • You can read values from it and store values into it • Indexing starts at 0 and stops at 1 less than the length • Just like Java list[9] = 142; printf("%d",list[9]);
Length of an array • The length of the array must be known at compile time • There is no length member or length() method • It is possible to find out how many bytes an array uses with sizeof intlist[100]; int size = sizeof(list);//400 • intlength = size/sizeof(int);//100
Arrays start filled with garbage • When you create an array, it is not automatically filled with any particular value • Inside the array (like any variable in C) is garbage • With regular variables, you might get a warning if you use a variable before you initialize it • With an array, you won't
Explicit initialization • Explicit initialization can be done with a list: • You can omit the size if you use an explicit initialization because the compiler can figure it out int primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; char grades[] = { 'A', 'B', 'C', 'D', 'F'};
memset() • The C standard library has a function called memset() that can set all the bytes in a chunk of memory to a particular value • Using it is guaranteed to be no slower than using a loop to initialize all the values in your array • It usually uses special instructions to set big chunks of memory at the same time intvalues[100]; memset(values, 0, sizeof(int)*100); //zeroes out array char letters[26]; • memset(letters, 'A', sizeof(char)*26); • //sets array to all 'A's
memcpy() • memset() is mostly useful for initialization (and usually only for zeroing things out) • memcpy() is a fast way to copy values from one array to another • Again, it's at least as fast as using your own loop • Again, it's somewhat dangerous since it lets you write memory places en masse intcubes[100]; int copy[100]; inti = 0; for( i = 0; i < 100; i++) cubes[i] = i*i*i; • memcpy(copy, cubes, sizeof(cubes));
Passing arrays to functions • Using an array in a function where it wasn't created is a little different • You have to pass in the length • The function receiving the array has no other way to know what the length is • sizeof will not work because it is based on what is known at compile time • The function should list an array parameter with empty square brackets on the right of the variable • No brackets should be used on the argument when the function is called • Like Java, arguments are passed by value, but the contents of the array are passed by reference • Changes made to an array in a function are seen by the caller
Array to function example • Calling code: • Function: intvalues[100]; inti = 0; for( i = 0; i < 100; i++ ) values[i] = i + 1; reverse(values, 100); void reverse(int array[], intlength) { intstart = 0; intend = length – 1; inttemp = 0; while( start < end ) { temp = array[start]; array[start++] = array[end]; array[end--] = temp; } }
Returning arrays • In C, you can't return the kind of arrays we're talking about • Why? • They are allocated on the stack • When a function returns, all its memory disappears • If you dynamically allocate an array with malloc(), you can return a pointer to it
Memory • An array takes up the size of each element times the length of the array • Each array starts at some point in computer memory • The index used for the array is actually an offset from that starting point • That’s why the first element is at index 0
A look at memory • We can imagine that we have an array of type int of length 10 • Let’s say the array starts at address 524 524 528 532 536 540 544 548 552 556 560 12 43 -9 6 789 0 -23 23 10 6 0 1 2 3 4 5 6 7 8 9 Addresses Indexes
Multidimensional arrays • It is legal to declare multidimensional arrays in C • They'll work just as you would expect • Except! You have to give the second dimension when passing to a function (otherwise, it won't know how big of a step to take when going from row to row) char board[8][8]; void clearBoard( char board[][8]) { inti = 0; intj = 0; for( i = 0; i < 8; i++ ) for( j = 0; j < 8; j++ ) board[i][j] = ' '; }
Array example • Write a program that reads an integer from the user saying how many values will be in a list • Assume no more than 100 • If the user enters a value larger than 100, tell them to try a smaller value • Read these values into an array • Find • Maximum • Minimum • Mean • Variance • Median • Mode
Components • C files • All the sources files that contain executable code • Should end with .c • Header files • Files containing extern declarations and function prototypes • Should end with .h • Makefile • File used by Unix make utility • Should be named either makefile or Makefile
C files • You can have any number of .c files forming a program • Only one of them should have a main() function • If the functions in a .c file will be used in other files, you should have a corresponding .h file with all the prototypes for those functions • whatever.c should have a matching whatever.h • Both the .c file that defines the functions and any that use them should include the header
Header files • Sometimes header files include other header files • For this reason, it is wise to use conditional compilation directives to avoid multiple inclusion of the contents of a header file • For a header file called wombat.h, one convention is the following: #ifndef WOMBAT_H #define WOMBAT_H //maybe some #includes of other headers //lots of function prototypes #endif
Compiling • When compiling multiple files, you can do it all on one line: • Alternatively, you can compile files individually and then link them together at the end gccmain.cutility.cwombat.c –o program gcc –c main.c gcc –c utility.c gcc –c wombat.c gccmain.outility.owombat.o –o program
Makefile • Compiling files separately is more efficient if you are only changing one or two of them • But it's a pain to type the commands that recompile only the updated files • That's why makefiles were invented • program: main.outility.owombat.o • gccmain.outility.owombat.o –o program • main.o: main.cutility.hwombat.h • gcc–c main.c • utility.o: utility.cutility.h • gcc–c utility.c • wombat.o: wombat.cwombat.h • gcc–c wombat.c • clean: • rm –f *.o program
Kernel • When people say OS, they might mean: • The whole thing, including GUI managers, utilities, command line tools, editors and so on • Only the central software that manages and allocates resources like the CPU, RAM, and devices • For clarity, people use the term kernel for the second meaning • Modern CPUs often operate in kernel mode and user mode • Certain kinds of hardware access or other instructions can only be executed in kernel mode
What does the kernel do? • Manages processes • Creating • Killing • Scheduling • Manages memory • Usually including extensive virtual memory systems • File system activities (creation, deletion, reading, writing, etc.) • Access to hardware devices • Networking • Provides a set of system calls that allow processes to use these facilities
Shells • A shell is a program written to take commands and execute them • Sometimes called a command interpreter • This is the program that manages input and output redirection • By default, one of the shells is your login shell, the one that automatically pops up when you log in (or open a terminal) • It's a program like any other and people have written different ones with features they like: • sh The original Bourne shell • csh C shell • kshKorn shell • bash Bourne again shell, the standard shell on Linux
Users and groups • On Linux, every user has a unique login name (user name) and a corresponding numerical ID (UID) • A file (/etc/passwd) contains the following for all users: • Group ID: first group of which the user is a member • Home directory: starting directory when the user logs in • Login shell • Groups of users exist for administrative purposes and are defined in the /etc/group file
Superusers • The superuser account has complete control over everything • This account is allowed to do anything, access any file • On Unix systems, the superuser account is usually called root • If you are a system administrator, it is recommended that you do not stay logged in as root • If you ever get a virus, it can destroy everything • Instead, administrators should log in to a normal account and periodically issue commands with elevated permission (often by using sudo)
Single file system • In Windows, each drive has its own directory hierarchy • C: etc. • In Linux, the top of the file system is the root directory/ • Everything (including drives, usually mounted in /mnt) is under the top directory • /bin is for programs • /etc is for configuration • /usr is for user programs • /boot is for boot information • /dev is for devices • /home is for user home directories
Files • There are regular files in Linux which you can further break down into data files and executables (although Linux treats them the same) • A directory is a special kind of file that lists other files • Links in Linux are kind of like shortcuts in Windows • There are hard links and soft links (or symbolic links) • File names can be up to 255 characters long • Can contain any ASCII characters except / and the null character \0 • For readability and compatibility, they should only use letters, digits, the hyphen, underscore, and dot • Pathnames describe a location of a file • They can start with / making them absolute paths • Or they are relative paths with respect to the current working directory
File permissions • Every file has a UID and GID specifying the user who owns the file and the group the file belongs to • For each file, permissions are set that specify: • Whether the owner can read, write, or execute it • Whether other members of the group can read, write, or execute it • Whether anyone else on the system can read, write, or execute it • The chmod command changes these settings (u is for owner, g is for group, and o is everyone else)
File I/O • All I/O operations in Linux are treated like file I/O • Printing to the screen is writing to a special file called stdout • Reading from the keyboard is reading from a special file called stdin • When we get the basic functions needed to open, read, and write files, we'll be able to do almost any kind of I/O
Processes • A process is a program that is currently executing • In memory, processes have the following segments: • Text The executable code • Data Static variables • Heap Dynamically allocated variables • Stack Area that grows and shrinks with function calls • A segmentation fault is when your code tries to access a segment it's not supposed to • A process generally executes with the same privileges as the user who started it
System calls • A system call is a way to ask the kernel to do something • Since a lot of interesting things can only be done by the kernel, system calls must be provided to programmers via an API • When making a system call, the processor changes from user mode to kernel mode • There is a fixed number of system calls defined for a given system
glibc • The most common implementation of the Standard C Library is the GNU C Library or glibc • Some of the functions in the glibc perform systems calls and some do not • There are slight differences between the versions of the glibc • Microsoft also has an implementation of the Standard C Library that doesn't always behave the same
Handling system errors • There are no exceptions in C • Instead, when a system call fails, it usually returns -1 • To find out why the system call failed • First, make sure you #include <errno.h> • Then check the value of the integer errno in your program after the system call fails • Use the man pages to determine what a given value of errno means • The perror() function is often used to print errors instead of printf() • It sends the output to stderr instead of stdout
Error handling example #include<stdio.h> #include<fcntl.h> #include<errno.h> int main() { intfd= open("eggplant.txt", O_WRONLY | O_CREAT | O_EXCL); if(fd == -1) { perror("Failure to create file: "); if( errno == EACCES ) perror("Insufficient privileges\n"); else if( errno == EEXIST ) perror("File already exists\n"); else perror("Unknown error\n"); exit(EXIT_FAILURE); } return 0; }
System types • C has a feature called typedef which allows a user to give a new name to a type • System types are often created so that code is portable across different systems • The most common example is size_t, which is the type that specifies length • It's usually the same as unsigned int • There are named types for process IDs (pid_t), group IDs (gid_t), user IDs (uid_t), time (time_t), and many others
Scope • The scope of a name is the part of the program where that name is visible • In Java, scope could get complex • Local variables, class variables, member variables, • Inner classes • Static vs. non-static • Visibility issues with public, private, protected, and default • C is simpler • Local variables • Global variables
Local scope • Local variables and function arguments are in scope for the life of the function call • They are also called automatic variables • They come into existence on the stack on a function call • Then disappear when the function returns • Local variables can hide global variables
Global scope • Variables declared outside of any function are global variables • They exist for the life of the program • You can keep data inside global variables between function calls • They are similar to static members in Java intvalue; void change() { value = 7; } intmain() { value = 5; change(); printf("Value: %d\n", value); return 0; }
Use of global variables • Global variables should rarely be used • Multiple functions can write to them, allowing inconsistent values • Local variables can hide global variables, leading programmers to think they are changing a variable other than the one they are • Code is much easier to understand if it is based on input values going into a function and output values getting returned