CSE 3430 MT2
Format specifiers: %i, %d, %f, %c, %s
%i, %d - to print signed decimal integer %.2f - to print float w 2 digits of precision (or some other num of digits of precision) %c - to print single character %s - to print a string
Meaning of operator precedence
- C operators classified by num operands which they take - operands are expressions (constants/vars/1+ operators) precedence - relationship b/n 2 operators in terms of the order in which the operations are performed - binary relation (defined wrt pairs of adjacent operators) - binary operators are adjacent if they have 1 operator in common, unary operators are adjacent if they have the same operand - can enforce a higher precedence w ( )
Indirect struct member access using struct pointer (struct *)
- access structure members via pointers to the structure ex. void Emp_fcn (struct Employee *ptr); struct Employee *ptr; ptr = &emp1; Emp_fcn(ptr); Emp_fcn must deref pointer by: (*ptr).first_name
Use of -> operator with struct pointers; rules for operands of -> operator
- access structure members via pointers to the structure ex. void Emp_fcn (struct Employee *ptr); struct Employee *ptr; ptr = &emp1; Emp_fcn(ptr); Emp_fcn must deref pointer by: ptr->first_name
Aggregate data types in C
- aggregate data types can hold more than one individual piece of data at a time 1. array - collection of values that are all the same data type 2. structure - collection of values (members) that may be of different types
Differences between arrays and structs
- array ele can be accessed w an index or subscript (bc all ele are of same size/type & stored contiguously) - structure members can be diff sizes/types, so they cannot be accessed with subscripts or indexes; they are instead given names (identifiers) & accessed by those names - unlike arrays, the name of a structure variable is NOT replaced w a pointer when used in an expression
Commands for redirection of input and/or output from the command line
- by default in Unix/Linux, C programs read input from the keyboard & write output to the screen - we can change this via redirection - < redirects input, > redirects output % prog1 < test_file > output_file --> this will run prog1, read input from test_file, and write output to output_file
How to initialize struct
- can also initialize x by assigning y to it since they are of the same type (cannot be done for arrays) ex. x = y; /* value of each mem in y is assigned to corr. mem in x */
C I/O functions: getchar
- can be used for input one character at a time - uses integer values which correspond to a given ASCII character - integer must be cast before being assigned to a char variable prototypes/declarations: int getchar (void); in code: newChar = getchar();
C I/O functions: putchar
- can be used for output one character at a time - uses integer values which correspond to a given ASCII character - integer must be printed w %c format code to be output as a char in code: newChar = getchar(); putchar(newChar); /* prints char in newChar variable */
Types of loops in C
- for - while - do while - break and continue
C I/O functions: scanf
- formatted input, manipulates standard I/O location (keyboard for input) - converts characters from standard in according to the format string and followed by pointer args (aka addresses) usually, indicating where the resulting values are stored int num; scanf("%i", &num); --> input: 23, num has value 23
C I/O functions: printf
- formatted output, manipulates standard I/O location (terminal display for output) - converts values to character form according to the format string & prints them to standard out
How to check that dynamic allocation succeeded
- if the requested memory cannot be allocated, malloc and calloc return null pointer (=0) - need to check that the pointer returned was not null ex. int *p; p = calloc(10,sizeof(int)); if (p != 0){ /* OK to access values in allocated storage */} else ( /* allocation failed */}
How to declare command line parameters in main in a C program
- if we want to pass params to main() in a program called myProg, we enter them on the command line: % myProg param1 param2 - args passed from command line will be placed in read-only memory (with string literals) - we must also declare params in main() inside myProg (2 options): 1. int main (int argc, char **argv) {...} 2. int main (int argc, char *argv[]) {...}
How to declare struct variables
- if you want a particular structure type throughout, use typedef or structure declaration w a tag before main - if you want a particular structure type in multiple source files, you should put tag declaration or typedef in a header file (no code, just function prototypes, typedef/struct def w tag)
Derived types in C
- infinite class of derived types constructed from the fundamental types in the following ways: 1. arrays of objects (vars/derived types) of a given type 2. pointers to objects of a given type 3. structures containing a sequence of objects (vars/derived types) of various types 4. unions capable of containing any of one of several objects of various types can be applied recursively: 1. array of pointers to some type 2. array of characters (aka string) 3. structures that contain points and so on
Rule for passing struct as parameter to function
- legal to pass structure var as a fcn arg - if passed by value, all values of all members must be copied and pushed onto the stack (not good) - can pass structure pointer as fcn arg, but dereferencing must be used inside of the fcn in order to access structure members --> only structures which are not much larger than a pointer should be passed by value - can use const keyword to prevent changing actual values
direct struct member access
- members of a structure are directly accessed w dot operator, which takes two operands: 1. left operand = structure variable (identifier which names declared structure var or a deref pointer to a structure variable) 2. right operand = name of a member of that type of structure variable ex. Tax_info is also a struct, can access members of it by: emp1.tax.tax_rate (tax_rate is a float stored in Tax_info structs)
C I/O
- no input/output defined in C itself --> fcns have been written into standard library for input and output - requires library stdio 2 basic types: character based - I: getchar() - O: putchar() formatted: scanf(), printf()
Storage class of function parameters in function definition
- no storage class (not stored until function declaration)
How to free dynamically allocated memory
- should free dynamically allocated memory once it is no longer being used - use free(), which returns void and has a single param (pointer to first byte of allocated storage to be freed) - declared in stdlib.h ex. int *p; p = calloc(10, sizeof(int)); if (p != NULL){ free(p);} p = NULL; /* ensure you do not attempt to access it (seg fault) */
Passing and accessing arrays
- to pass an array as a param, use its name & must also pass its size (no library function tells you array size - no array termination marker is stored) ex. sumArray(floatArray, size); - inside the function, elements of the array can be accessed using an index/subscript ex. sum = floatArray[i]; - to declare the params for the function: ex. float sumArray(float *floatArray, int size); /* function declaration *. float sumArray(float *floatArray, int size) /* function definition */ { statement(s); }
what are argc and argv?
1. argc - contains count of command line arguments (program + parameters) --> arg counter - guaranteed that argc is non-neg 2. argv - contains pointers to the individual arguments as character strings (argv[] is an array of char*) --> arg vector - guaranteed that argv is a NULL pointer
Characteristics of C as a programming language
1. low overhead 2. fast 3. no automatic garbage collection (software writer has to do explicit memory mgmt when required & failure to do so can cause memory leaks, where the memory may grow potentially w/o bound) 4. powerful (OSs, device drivers and embedded systems are written in C)
structure basics
1. may be passed as args to functions (by value or reference) 2. may be returned by fcns 3. structures of same type may be assigned to one another (not true of arrays, but arrays w/in a structure copy correctly) 4. can declare pointers to structures 5. can take the address of a structure variable 6. can declare arrays of structures
Read-only versus read-write strings in C (and where they are stored in memory)
1. read-only (string literals) - anything in double quotes not allocated as a var ex. "%s %s\n" /* string literals iin scanf() or printf() */ char *title = "A Tale of Two Cities"; /* pointer is allocated space, string is not */ 2. read-write (arrays of characters) - anything declared w/in program as an array of data type char where the binary values in each byte are interpreted as ASCII characters - string literals and char array strings must be terminated w NULL character '\0' (automatically inserted unless defining ASCII char by ASCII char) ex. char title[] = "U S"; char title[8] = {'U',' ','S','\0'};
storage locations
1. register - small num words of fast memory inside CPU - data which will be accessed soon/repeatedly - allocated when fcn is called and deallocated when the fcn returns 2. stack - place in mem where info specific to a particular fcn is stored each time it's invoked - allocated when fcn is called and deallocated when fcn returns - when a fcn stops executing or returns, any var declared and stored in the stack is no longer avail 3. heap - place in memory where info specific to a particular process is stored each time it is invoked - any values stored here are avail until the process stops executing - where calloc() and malloc() memory addresses are - essential for values that must be persistent w/in a process no matter what fcn is currently executing
errors at compile/build time
1. syntax errors - make a program invalid 2. linkage errors - compiler will not generate an executable / machine code program version
Declaration of constants in C
2 methods: 1. literal constant: put the const keyword after or before type keyword (declared const must be initialized with its value as part of the declaration, bc compiler won't allow assignments later) ex. float const PI = 3.14f; ex. const float PI = 3.14f; 2. symbolic constant: preprocessor #define directive; can be used to define a constant, statement or mathematical expression ex. #define <name> <value> (note: no ; for preprocessor directives) - <name> is a text string (no white space), <value> is any text string (can be a math expression) - cannot change value later - all occurrences are replaced by preprocessor before program is compiled ex. #define TRUE 1 - (2) symbolic constant can be used anywhere a literal constant can be used, but (1) constants def w const keyword can only be used where vars are used
Encoding of null byte terminator('\0') as ASCII character
All 8 bits are 0 - length of a string in num characters NOT incl null character (actual size = length string + 1)
Addtl differences between C and Java/C++
C is a subset of C++ 1. C is procedural, Java/C++ are procedural & objected-oriented 2. C is fully compiled to machine code, Java/C++ is compiled to byte term-70code and then to machine code 3. C/C++ allow direct manipulation of memory via pointers, Java has references (not pointers) 4. C/C++ do not have automatic garbage collection, Java does
Differences between C and Java/C++
C: 1. direct memory manipulation 2. platform dependent primitives 3. manually managed memory (no garbage collector) 4. all variables declared up front (in ANSI C) -> no just-in-time declaration 5. NOT object oriented (no classes/objects, no encapsulation since all memory is accessible/modifiable by any instruction of an executable, no class inheritance) Java/C++: 1. primitive types + object references 2. allows just-in-time declaration 3. exception handling Only Java: 1. platform-indep primitives 2. garbage collected memory
When self-referential struct declaration is invalid; when it is valid
INVALID: struct Self_Ref1{ int a, b; struct Self_Ref1 c; }; - structure member c contains another complete structure member c (infinitely recursive) VALID: struct Self_Ref2{ int a, b; struct Self_Ref2 *c; }; - used to build linked data structures (linked lists/trees) - structure does not contain a member that is another structure of the same type, but rather a pointer to such - the compiler can allocate space for the pointer
Systems programs used to build C source code files to executable (and input and output files for each systems program); order in which these systems programs run to build a C source file to an executable
Preprocessor, Compiler, Assembler, Linker
How parameters are passed from the command line
all command line arguments enter a C program as read-only ASCII strings - may not be stored in contiguous locations in memory, bc argv is an array of pointers to these strings
Usefulness of argv[0]
argv[0] points to the name of the program
Meaning of operator associativity
associativity relevant when 2 adjacent operators have the same precedence L-R associativity - operation specified by leftmost operator is done first R-L associativity - opposite order
Storage class: automatic
auto (keyword) - the runtime stack - default storage class for vars inside blocks - discarded exit from block - can have auto specifier (redundant) - can have register specifier (stored in fast registers if possible instead of RAM)
break & continue
break - exits innermost loop / switch statement which encloses it regardless of loop conditions continue - causes loop to stop its current iteration, do the adjustment (if for loop) and begin execution again. may only occur inside for, while or do-while loops
Definition of string in C
char *string1 = "warehorse"; char string2[] = "conteiner"; INVALID: string1[6] = 'u'; - chars in string literal cannot be changed VALID: string1 = "warehouse"; - string1 now points to new string literal & address to prior string literal is lost VALID: string2[4] = 'a'; - any ASCII char in a char array string can be changed (they are vars)
Assignment of strings: Which assignments are valid, and which are invalid?
char *string1; char string2[] = "Go Ducks!"; string1 = string2; string1[3] = 'B'; no seg fault bc string 1 points to RW string printf("string1 is: %s", string1); can pass by reference only w strings (outputs string stored at string1 address) string2 = string1; INVALID bc you cannot assign a char * type of string to a char array type of string
Difference between compile time (static events) and run time (dynamic events)
compile time - events that occur when a program is being compiled/built run time - events that occur when the program is being executed/running
String operations in C library (You do not have to know them, except strlen() and strcmp() )
contained in ctype.h - each function takes an integer arg which contains a ASCII character value - all these fcns return an integer value which is used as a Boolean strlen() - finds length of a string strcmp() - compares 2 strings
if, else-if
dangling else - compiler pairs any else w the closest/most recent unmatched if which is not enclosed in a diff block --> make sure to enclose each if / else if statement in { }
Difference between declaration and definition of variables and of functions: declaration
declaration: type information only, no value(s) - variable: tells compiler type of variable (not its value) - function: tells compiler the return type of a function & the number and types of its params (param names are optional) - var can only be declared once in a given block in a C program, or once outside of any block in a given source file - function can be declared multiple times in a C program, as long as all declarations are consistent on data types - vars/functions must be declared (but not nec defined) before they can be referenced in a non-declarative statement
Scope of function parameters in function definition
default: block (can't be changed)
Difference between declaration and definition of variables and of functions: definition
definition: type information AND value(s) - variable: tells compiler the type of variable and its initial value - function: tells compiler the return type, param types, and the code/statements that should be executed when the function is called - given variable/function can only be defined once in a C program - definition is also a declaration, since it contains type information
How to determine scope of variable in program
depends on where the variable is declared
do while loop
do { statement(s); }while (expression); - statement(s) executed once, then expression is eval - if non-zero (TRUE), statement(s) are executed until expression eval to 0 (FALSE) - body always eval once even if expression is false before first execution
Use of malloc and calloc for dynamic allocation
dynamic/runtime memory allocation - requesting addtl static storage class space in memory while program is executing (do not know while coding how much storage is needed) - malloc & calloc return a pointer to void which points to the address of the first byte of allocated memory space on the heap. if allocation fails, return null pointer. - if multiple bytes are allocated, they will be contiguous
Difference between static arrays in C and dynamic arrays
dynamically allocated arrays - C library function called to request space for array elements at runtime - need to declare a pointer to an array of specific type to hold the address of this block in memory
For loops in C
for (expression1; expression2; expression3) { statement(s); } exp1 = initialization (evaluated once before exp2 is evaluated the first time) exp2 = condition (evaluated once before each execution of the body; if it evaluates to a non-zero value, the body is executed; otherwise execution of the loop terminates) exp3 = adjustment (evaluated after all statements in the body are executed and just before the condition is evaluated again)
Type rule for & operator
for variable of typeX, the type of &variable is pointer to typeX (typeX *) ex. - j is int, &j is int* - setsPtr is int **, &setsPtr is int***
Type rule for * operator
for variable which is a pointer to typeX (typeX *), the type of *variable is typeX ex. - jPtr is int*, *jPtr is int - setsPtrPtr is int***, *setsPtrPtr is int**
void pointer
general-purpose pointer that points to data type void; used to hold references to any data type; any pointer can be assigned to a pointer to void - malloc() & calloc() return a void *, which can then be assigned to a pointer to any other type - without casting a void pointer, the compiler won't know how many bytes to read starting a the given address ex. void *void_ptr; int var1 = 1; void_ptr = &var1; printf("*void_ptr = %d", *void_ptr); /* INVALID - cannot deref pointer without cast */ printf("*void_ptr = %d", (int *)void_ptr); /* VALID */
Rules for valid identifiers in C
identifiers - names for vars/constants/types/functions 1. can use a-z, A-z, 0-9 and _ 2. case sensitive 3. first character must be a letter or _ (but _ used for sys purposes, don't use) 4. keywords are reserved words & may not be used as identifiers
* and & meanings
in a declaration: *: "I am a variable that contains an address" that points to a certain type of value in a statement: &: "get the address of a variable" *: "access (read/write) the value at the address in the variable which follows *"
Indirect access using pointer
indirect access - access variable through its address stored in a pointer int *p, c=10; p = &c; /* variable p now stores address of variable c; p points to variable c */ printf("%i", c); printf("%i", *p); /* both of these statements output 10 */ *p = 1; /* c now equals 1, not 10 */
Built-in (basic) data types in C
integer types: char - smallest addressable unit (8 bits); each byte has own address short - not common; 16 bits int - default type for an integer constant value; typically 32 bits long - not needed really; typically 32 bits long long - 64 bits on platforms that support it floating point types: float - single precision (6 decimal digits of precision) double - double precision (about 15 decimal digits of precision); constant default unless suffixed with 'f' - no fixed/max size for a type in C except for char (size dep on implementation), but following must hold: - char <= short <= int <= long - float <= double <= long double
Linkage: external, internal, none/no linkage
linkage - determines whether the same name in a diff scope refers to the same var/fcn or some diff var/fcn for a given name (identifier) - linkage only relates to file scope vars and fcns 1. None/no linkage - identifiers are individuals; multiple declarations using the same identifier are always treated as separate & distinct entities - all block scope vars and params in fcn prototypes have no linkage 2. internal linkage - all ref to the identifier w/in 1 source file refer to a single var (the one declared in that source file) but declarations of and ref to the same identifier in other source files refer to diff vars 3. external linkage - all ref to an identifier in any source file refer to the same entity - var known to all fcns in the program; declared outside the fcn
malloc vs calloc
malloc - returns void * which points to address of 1st byte of allocated memory space on the heap; 1 param = sizeof() which specifies num of bytes we are requesting on the heap - memory returned is uninitialized pointers (contains garbage values) ex. int *p; p = malloc(4*sizeof(int)); /* want space for 4 ints */ calloc - same as malloc but 2 params: expressions that specify num elements for which storage is being requested and the size of each in bytes (use sizeof()) - memory returned is initialized to 0 (use calloc if u do not plan on initializing values) ex. int *p; p = calloc(4, sizeof(int));
How to convert expression with (), * and and . to equivalent expression with ->
op1->op2->op3 == (*(*op1).op2).op3 ex. reference gross_salary by: emp_ptr->tax.gross_salary (tax is a struct member, not pointer)
How pointers are used to pass parameters in C; pass by value versus pass by reference
pass by value - sends a copy of values a & b (placed on the stack before execution), but function1 will not have access to memory where a & b are stored --> cannot alter their values ex. int a=5, b=10; function1(a,b); pass by reference - pass a pointer to the parameter, allowing the function to alter the variable in the calling environment - array ele cannot be passed by value unless each element is passed as an individual parameter ex. void swap(int *x, int *y); /* FCN DECLARATION */ int a=10, b=5; swap(&a, &b); /* CALLING SWAP */ /* CODE FOR SWAP: */ void swap (int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp;}
Pointers in C: Definition of pointer, type of a pointer
pointer - a variable that stores the 8-byte address of a specific data type in memory ex. int b; int *int_ptr; int_ptr = &b; /* can get to the same memory location either by using the variable b or by referencing the address stored in int_ptr */ ex. float *flt_ptr; /* cannot be used to store address of an int */
NULL pointer definition (address 0)
pointer which points to 0 (INVALID). Uses: a) To initialize a pointer variable when that pointer variable isn't assigned any valid memory address yet. b) To pass a null pointer to a function argument when we don't want to pass any valid memory address - cannot be dereferenced
What pointers in argv point to; what argv[argc] is
pointers in argv point to program & its params ex. argv[0] = myProg argv[1] = param1 argv[2] = param2... argv[argc] = NULL pointer
Scope of function parameters in function declaration
prototype scope, can't change
Declaration of variables in C
purpose: define var/constant before it's used format: type identifier (, identifier); initial value: can be assigned but not required unless it's a constant ex. int i, j = 5, k; char code, category; int i = 123; casting - type conversion; casting larger types to smaller types is dangerous ex. code block: int i = 65; char ch; /* range -128 to 127) ch = (char) i; /* ch now equals 65 */
Storage class: register
register (keyword) - hardware registers
Scope: file, block, prototype
scope - determines the region of a program in which a variable can be accessed directly (by using its name not through a pointer 1. file - any identifier declared outside of all blocks has file scope - identifier may be accessed anywhere from the end of its declaration to end of source file in which declared 2. block - list of statements enclosed in braces - any identifiers declared at the beg of block are accessible to all statements in the block (block scope w/in block) - formal params of a fcn also have block scope - outer block vars cannot be referenced by name from w/in inner blocks if they have the same name 3. prototype scope - any var w prototype scope has no memory class (static/automatic/register) bc no memory has been allocated for the var - applies to param names given in a fcn declaration (not fcn name) - extends uniquely to each prototype ex. void fcn1 (int var1, int var2); - var1 and var2 have prototype scope, no memory allocated for these at this time
What happens if program attempts to write character(s) in read-only string?
segmentation faults - only way to change the string string1 points to is string1 = "quip"; ex. char *string1 = "quit"; /* cannot change "quit" */
errors at run time
semantic errors - errors that the compiler does not discover, but generate an exception when running, causing the OS to terminate the program - do not make a program invalid, bc only valid programs can be built & executed ex. division by 0
Storage class: static
static (keyword) - the heap - default for vars declared outside of any block - when keyword static is used w/in a block, it changes a var's storage class (automatic --> static) - when keyword static is used outside of any/all blocks, it changes a variable's linkage (external --> internal) Note: external linkage means the symbol (function or global variable) is accessible throughout your program and internal linkage means that it is only accessible in one translation unit.
Difference between static arrays in C and dynamic arrays in C
statically allocated arrays - compiler generates code to allocate the space for the array elements at compile time (and to initialize them, if they are initialized as part of the declaration); space is allocated on the stack/heap depending upon the declaration - fixed size - expression in [ ] must be a constant w known value at compilation time (can only be empty if we give initial array values) - array elements initialized to 0 if on the heap & initial values are not given ex. int scores[6]; ex. int scores[] = {100, 85, 67, 94, 96, 78}; ex. int scores[6] = {100, 85}; /* last 4 elements initialized to 0 */ Note: scores and &scores[0] are both constant pointers to the first element of the array (cannot be changed); all array elements are stored in contiguous memory locations Note: array indexes start at 0 - accessing elements beyond last element causes a run-time error (typically segmentation fault)
Storage class
storage class - determines the type of storage (and its lifetime) associated with a variable and the variable's initialization - determines when the var is created and destroyed and how long it will retain its value - determines whether the var will be initialized by compiler or whether it must be done explicitly by the program code default storage class for a var depends on where it is declared
Importance of null byte terminator for strings in C
string = sequence of 0+ characters which must be terminated by a null character '\0' - no string can contain this except at its end - null string contains null character as its 1 element - library fcns use it to determine where string ends (length of string --> don't pass size/length to fcns) - if null char is missing --> seg faults char string[] {'e','x','a','m','\0','A'}; printf("%s\n", string); OUTPUT: exam
How to declare struct type
struct tag { member-list with type of each member } variable list; - struct is a keyword - tag field and variable-list field are each optional, but at least one is required - if tag is omitted, only vars w identifiers which appear in the variable-list field are declared to be of this structure type and no other vars of this type can be declared subsequently - if tag is included, var-list field can be empty, and tag can be used later to declare vars of this structure type (required if you use malloc/calloc) - can also declare struct w typedef keyword (says create new data type called Simple that is a structure which contains ...) ex1. with a tag (Simple) struct Simple{ int a; float b; } struct Simple x, y[10], *z; ex2. no tag struct{ int a; float b; } x, y[10], *z; ex3. typedef typedef struct{ int a; float b; } Simple; Simple x, y[10], *z;
Rule for assignment of one struct variable to another struct variable
structures of the same type may be assigned to one another (not true of arrays! but if array is in structure, it copies correctly)
Pointer types
unsigned int *p; char *c; void *x; int **y; p: pointer to unsigned int c: char pointer x: void pointer y: pointer to an integer pointer
Use of const keyword to pass pointer to read-only array or read-only struct
use const keyword if the function will not write to the data pointed to by the pointer when passing by reference ex. fcn sums ele in an array given address & size int sum(const int *array, int size); int array[6] = {18, 16, 15, 20, 19, 17}; int size = 6; int total; total = sum(array, size); OR total = sum(&array[0], size);
How to determine storage class of variable in program
where in memory each type if stored, and how they are initialized
How to determine linkage of variable in program
where variables are declared - only file scope vars have linkage 1. none - block scope vars and params in fcn prototypes have no linkage 2. internal - file scope var with "static" keyword 3. external - default for file scope var
while loops
while (expression) { statement(s); } expression is evaluated --> if non-zero (TRUE), body is executed & expression is eval again --> if zero (FALSE), execution of loop terminates Note: can omit {} for one-line loops (for, while and do-while)