C Boot Camp September 30, 2018
Copyright By PowCoder代写 加微信 powcoder
¡ö C Basics
¡ö Debugging Tools / Demo
¡ö Appendix
C Standard Library getopt
stdio.h stdlib.h string.h
C Basics Handout
cd ~/private
wget http://cs.cmu.edu/~213/activities/cbootcamp.tar.gz tar xvpf cbootcamp.tar.gz
cd cbootcamp
¡ö Contains useful, self-contained C examples
¡ö Slides relating to these examples will have the file
names in the top-right corner!
¡ö The minimum you must know to do well in this class
¡ö You have seen these concepts before
¡ö Make sure you remember them.
¡ö Summary:
¡ö Pointers/Arrays/Structs/Casting
¡ö Memory Management
¡ö Function pointers/Generic Types
¡ö Strings
¡ö GrabBag (Macros, typedefs, header guards/files, etc)
¡ö Stores address of a value in memory ¡ö e.g. int*, char*, int**, etc
¡ö Access the value by dereferencing (e.g. *a).
Can be used to read or write a value to given address
¡ö Dereferencing NULL causes undefined behavior
(usually a segfault)
¡ö Pointer to type A references a block of sizeof(A) bytes
¡ö Get the address of a value in memory with the ¡®&¡¯
¡ö Pointers can be aliased, or pointed to same address
Call by Value vs Call by Reference
./passing_args
¡ö Call-by-value: Changes made to arguments passed to a function aren¡¯t reflected in the calling function
¡ö Call-by-reference: Changes made to arguments passed to a function are reflected in the calling function
¡ö C is a call-by-value language
¡ö To cause changes to values outside the function, use pointers
¡ö Do not assign the pointer to a different value (that won¡¯t be reflected!)
¡ö Instead, dereference the pointer and assign a value to that address
void swap(int* a, int* b) { int temp = *a;
*b = temp;
int x = 42;
int y = 54;
swap(&x, &y); printf(¡°%d£¤n¡±, x); // 54 printf(¡°%d£¤n¡±, y); // 42
Pointer Arithmetic
./pointer_arith
Can add/subtract from an address to get a new address
¡ö Only perform when absolutely necessary (i.e., malloclab)
¡ö Result depends on the pointer type
A+i, where A is a pointer = 0x100, i is an int
¡ö int* A: A+i=0x100+sizeof(int) *i=0x100+4*i
¡ö char* A: A+i = 0x100 + sizeof(char) * i = 0x100 + 1 * i
¡ö int**A: A+i=0x100+sizeof(int*)*i=0x100+8*i
Rule of thumb: explicitly cast pointer to avoid confusion
¡ö Prefer ((char*)(A) + i) to (A + i), even if A has type char*
¡ö Collection of values placed under one name in a single
block of memory
¡ö Can put structs, arrays in other structs
¡ö Given a struct instance, access the fields using the ¡®.¡¯ operator
¡ö Given a struct pointer, access the fields using the ¡®->¡¯ operator
struct inner_s { struct outer_s {
outer_s out_inst; out_inst.ar[0] = ¡®a¡¯; out_inst.in.i = 42;
outer_s* out_ptr = &out_inst; out_ptr->in.c = ¡®b¡¯;
int i; char c;
char ar[10];
struct inner_s in;
¡ö When to use
¡ö Saving memory
¡ö Malloclab! ¡ö Tagged Unions
typedef union {
} myUnion;
myUnion *u = malloc(sizeof(myUnion))
printf(¡±size: %zu£¤n¡±, sizeof(myUnion));
u->a = ¡®A¡¯;
printf(¡°u->b: %d¡±, u->b); // UNDEFINED
Arrays/Strings
¡ö Arrays: fixed-size collection of elements of the same type
¡ö Can allocate on the stack or on the heap
¡ö int A[10]; // A is array of 10 int¡¯s on the stack
¡ö int* A = calloc(10, sizeof(int)); // A is array of 10
int¡¯s on the heap
¡ö Strings: Null-character (¡®£¤0¡¯) terminated character arrays
¡ö Null-character tells us where the string ends
¡ö All standard C library functions on strings assume null-termination.
¡ö Can convert a variable to a different type
¡ö Integer Casting:
¡ö Signed <-> Unsigned: Keep Bits – Re-Interpret
¡ö Small -> Large: Sign-Extend MSB
¡ö Cautions:
¡ö Cast Explicitly: int x = (int) y instead of int x = y
¡ö Casting Down: Truncates data
¡ö Cast Up: Upcasting and dereferencing a pointer causes undefined
memory access
¡ö Rules for Casting Between Integer Types
Malloc, Free, Calloc
¡ö Handle dynamic memory allocation on HEAP
¡ö void* malloc (size_t size):
¡ö allocate block of memory of size bytes
¡ö does not initialize memory
¡ö void* calloc (size_t num, size_t size):
¡ö allocate block of memory for array of num elements, each size bytes long
¡ö initializes memory to zero
¡ö void free(void* ptr):
¡ö frees memory block, previously allocated by malloc, calloc, realloc, pointed by ptr
¡ö use exactly once for each pointer you allocate
¡ö size argument:
¡ö should be computed using the sizeof operator
¡ö sizeof: takes a type and gives you its size
¡ö e.g., sizeof(int), sizeof(int*)
Memory Management Rules
¡ö malloc what you free, free what you malloc
¡ö client should free memory allocated by client code
¡ö library should free memory allocated by library code
¡ö Number mallocs = Number frees
¡ö Number mallocs > Number Frees: definitely a memory leak
¡ö Number mallocs < Number Frees: definitely a double free
¡ö Free a malloc¡¯ed block exactly once
¡ö Should not dereference a freed memory block
¡ö Only malloc when necessary
¡ö Persistent, variable sized data structures
¡ö Concurrent accesses (we¡¯ll get there later in the semester)
mem_mgmt.c
./mem_valgrind.sh
Stack vs Heap vs Data
¡ö Local variables and function arguments are placed on the
¡ö deallocated after the variable leaves scope
¡ö do not return a pointer to a stack-allocated variable!
¡ö do not reference the address of a variable outside its scope!
¡ö Memory blocks allocated by calls to malloc/calloc are placed on the heap
¡ö Globals, constants are placed in data section
¡ö Example:
¡ö // a is a pointer on the stack to a memory block on the heap
¡ö int* a = malloc(sizeof(int));
¡ö Creates an alias type name for a different type
¡ö Useful to simplify names of complex data types
¡ö Be careful when typedef-ing away pointers!
struct list_node {
./typedefs
typedef int pixel;
typedef struct list_node* node;
typedef int (*cmp)(int e1, int e2); // you won¡¯t use this in 213
pixel x; // int type
node foo; // struct list_node* type
cmp int_cmp; // int (*cmp)(int e1, int e2) type
¡ö A way to replace a name with its macro definition
¡ö No function call overhead, type neutral
¡ö Think ¡°find and replace¡± like in a text editor
¡ö defining constants (INT_MAX, ARRAY_SIZE)
¡ö defining simple operations (MAX(a, b))
¡ö 122-style contracts (REQUIRES, ENSURES)
¡ö Warnings:
¡ö Use parentheses around arguments/expressions, to avoid problems after
substitution
¡ö Do not pass expressions with side effects as arguments to macros
#define INT_MAX 0x7FFFFFFFF
#define MAX(A, B) ((A) > (B) ? (A) : (B)) #define REQUIRES(COND) assert(COND)
#define WORD_SIZE 4
#define NEXT_WORD(a) ((char*)(a) + WORD_SIZE)
Generic Types
¡ö void* type is C¡¯s provision for generic types
¡ö Raw pointer to some memory location (unknown type)
¡ö Can¡¯t dereference a void* (what is type void?)
¡ö Must cast void* to another type in order to dereference it
¡ö Can cast back and forth between void* and other pointer types
// stack implementation:
typedef void* elem;
stack stack_new();
void push(stack S, elem e);
elem pop(stack S);
// stack usage:
int x = 42; int y = 54;
stack S = stack_new():
push(S, &x);
push(S, &y);
int a = *(int*)pop(S);
int b = *(int*)pop(S);
Header Files
Includes C declarations and macro definitions to be shared across multiple files
¡ö Only include function prototypes/macros; implementation code goes in .c file!
Usage: #include
¡ö #include ¡°file¡± for your source files (eg #include ¡°header.h¡±)
¡ö Never include .c files (bad practice)
struct list_node {
struct list_node* next; };
typedef struct list_node* node;
node new_list();
void add_node(int e, node l);
#include ¡°list.h¡±
node new_list() {
// implementation
void add_node(int e, node l) { // implementation
// stacks.h
#include ¡°list.h¡±
struct stack_head {
node bottom;
typedef struct stack_head* stack
stack new_stack();
void push(int e, stack S);
Header Guards
¡ö Double-inclusion problem: include same header file twice
//grandfather.h //father.h //child.h
#include ¡°grandfather.h¡± #include ¡°father.h¡±
#include ¡°grandfather.h¡±
Error: child.h includes grandfather.h twice
¡ö Solution: header guard ensures single inclusion
//grandfather.h #ifndef GRANDFATHER_H #define GRANDFATHER_H
//father.h #ifndef FATHER_H #define FATHER_H
#include ¡°father.h¡± #include ¡°grandfather.h¡±
Okay: child.h only includes grandfather.h once
Debugging GDB, Valgrind
¡ö No longer stepping through assembly!
Some GDB commands are different:
¡ö si / si ¡ú step / next
¡ö break file.c:line_num
¡ö disas ¡ú list
¡ö print
¡ö Use TUI mode (layout src)
¡ö Nice display for viewing source/executing
¡ö Buggy, so only use TUI mode to step
through lines (no continue / finish)
¡ö Find memory errors, detect memory leaks
¡ö Common errors:
¡ö Illegal read/write errors
¡ö Use of uninitialized values
¡ö Illegal frees
¡ö Overlapping source/destination addresses
¡ö Typical solutions
¡ö Did you allocate enough memory?
¡ö Did you accidentally free stack
variables/something twice?
¡ö Did you initialize all your variables?
¡ö Did use something that you just free¡¯d?
¡ö –leak-check=full
¡ö Memcheck gives details for each
definitely/possibly lost memory block (where it was allocated
C Program Memory Layout
Variable Declarations & Qualifiers
¡ö Global Variables:
¡ö Defined outside functions, seen by all files
¡ö Use ¡°extern¡± keyword to use a global variable defined in another file
¡ö Const Variables:
¡ö For variables that won¡¯t change
¡ö Data stored in read-only data section
¡ö Static Variables:
¡ö For locals, keeps value between invocations
¡ö USE SPARINGLY
¡ö Note: static has a different meaning when referring to functions
¡ö Volatile Variables:
¡ö Compiler will not make assumptions about current value, useful for
asynchronous reads/writes, i.e. interrupts
¡ö ¡°volatile¡± == ¡°subject to change at any time¡±
C Libraries
string.h: Common String/Array Methods
¡ö One the most useful libraries available to you
¡ö Used heavily in shell/proxy labs
¡ö Important usage details regarding
arguments:
¡ö prefixes: str -> strings, mem -> arbitrary
memory blocks.
¡ö ensure that all strings are ¡®£¤0¡¯ terminated!
¡ö ensure that dest is large enough to store src!
¡ö ensure that src actually contains n bytes!
¡ö ensure that src/dest don¡¯t overlap!
string.h: Common String/Array Methods
¡ö Copying:
¡ö void *memcpy (void *dest, void *src, size_t n)
Copy n bytes of src into dest, return dest
¡ö char *strcpy(char *dest, char *src)
Copy src string into dest, including the NUL terminator, return dest. Make sure dest is large enough to contain src.
¡ö char *strncpy(char *dest, char *src, size_t count) Copy src string into dest, including the NUL terminator, return dest. Copies at most count bytes.
Make sure dest is large enough to contain src.
string.h: Common String/Array Methods (Continued)
¡ö Concatenation:
¡ö char *strncat (char *dest, char *src, size_t n)
Append copy of src to end of dest reading at most n bytes, return dest
¡ö char *strcat (char *dest, char *src)
Works for arbitrary length strings, but has the safety issues you¡¯ve seen in attacklab
string.h: Common String/Array Methods (Continued)
¡ö Comparison:
¡ö int strncmp (char *str1, char *str2, size_t n)
Compare at most n bytes of str1, str2 by character
(based on ASCII value of each character, then string length), return comparison result
-1 if str1 < str2
0 if str1 == str2
1 if str1 > str2
¡ö int strcmp(char *str1, char *str2)
Compare str1 to str2.
Make sure each string is long enough to be safely compared.
string.h: Common String/Array Methods (Continued) ¡ö Searching:
¡ö char *strstr (char *str1, char *str2)
Return pointer to first occurrence of str2 in str1, else NULL
¡ö char *strtok (char *str, char *delimiters) Tokenize str according to delimiter characters provided in delimiters.
Return the one token for each strtok call, using str = NULL
string.h: Common String/Array Methods (Continued)
¡ö size_t strlen (const char *str)
Return length of the string (up to, but not including the ¡®£¤0¡¯ character)
¡ö void *memset (void *ptr, int val, size_t n)
Set first n bytes of memory block addressed by ptr to val.
Use for setting bytes only. Don¡¯t use it to set or initialize int arrays, for example.
stdlib.h: General Purpose Functions ¡ö Dynamic memory allocation:
¡ö malloc, calloc, free ¡ö String conversion:
¡ö int atoi(char *str):parsestringintointegralvalue(return0ifnotparsed)
¡ö System Calls:
¡ö void exit(int status):terminatecallingprocess,returnstatustoparentprocess
¡ö void abort():abortsprocessabnormally
¡ö Searching/Sorting:
¡ö provide array, array size, element size, comparator (function pointer)
¡ö bsearch: returns pointer to matching element in the array
¡ö qsort: sorts the array destructively
¡ö Integer arithmetic:
¡ö int abs(int n): returns absolute value of n
¡ö size_t: unsigned integral type (store size of any object)
¡ö In a format string, print with %zu
¡ö Another really useful library.
¡ö Used heavily in cache/shell/proxy labs
¡ö Used for:
¡ö argument parsing
¡ö file handling
¡ö input/output
¡ö printf, a fan favorite, comes from this library!
stdio.h: Common I/O Methods
¡ö FILE *fopen (char *filename, char *mode): open the file with
specified filename in specified mode (read, write, append, etc), associate
it with stream identified by returned file pointer
¡ö int fscanf (FILE *stream, char *format, …): read data
from the stream, store it according to the parameter format at the
memory locations pointed at by additional arguments.
¡ö int fclose (FILE *stream): close the file associated with stream
¡ö int fprintf (FILE *stream, char *format, … ): write the
C string pointed at by format to the stream, using any additional arguments to fill in format specifiers.
¡ö Needtoinclude unistd.htouseint main(int argc, char **argv)
int opt, x;
/* looping over arguments */ while((opt=getopt(argc,argv,¡°x:”))>0){
switch(opt) {
x = atoi(optarg);
printf(¡°wrong argument£¤n”);
¡ö Used to parse command-line arguments.
¡ö Typically called in a loop to retrieve arguments
¡ö Switch statement used to handle
¡ö colonindicatesrequiredargument
¡ö optarg is set to value of option
¡ö Returns -1 when no more
arguments present
¡ö See recitation 6 slides for more
Note about Library Functions
¡ö These functions can return error codes
¡ö malloc could fail
if ((x = malloc(sizeof(int))) == NULL) printf(¡°Malloc failed!!!£¤n¡±);
¡ö a file couldn¡¯t be opened
¡ö a string may be incorrectly parsed
¡ö Remember to check for the error cases and handle the
errors accordingly
¡ö may have to terminate the program (eg malloc fails)
¡ö may be able to recover (user entered bad input)
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com