Programming in C - Part 2
CPSC 457
Mohammad Reza Zakerinasab
May 11, 2016
These slides are forked from slides created by Mike Clark
Where to find these slides and related source code?
http://goo.gl/k1qIxB
http://pages.cpsc.ucalgary.ca/~mrzakeri/s2016/Tut2-
source-code.zip
● I will set up a web page for the tutorial sessions this weekend.
Programming in C - Part 1 - Review
● Why programming in C?
● The structure of a simple C program
● Preprocessor directives & header files
● Data types
● Operators
● Control structures
● Data Structures
● Compilation & linking
Hello World Example
#include <stdio.h>
int main() {
/* my first program in C */ printf("Hello, World! \n");
return 0;
}
Structured Data Types: ArraysArrays
- Can be a static or dynamic allocation
Static
(Declaration, and allocation)
Can be accessed using an index.
Ex.
Dynamic
(Declaration)
(Allocation)
(Deallocation)
Structured Data Types: StructuresComposed of primitives and other user-defined types (structs).
…
Commonly, you will want to use typedef to alias the typename to something shorter.
Accessing struct fields is done with the dot character:
Structured Data Types: UnionsUnions
- Similar to a structure, but the fields overlap each other.
- The size needed to allocate a union is determined by the largest size of the fields.
- Each field can be addressed, the value accessed will be determined by the type of
the field
Example
Control StructuresConditional Examples
if, else if, else
switch
Looping
do
while
for
Compiling and linkingMakefile
Used to build things. Building C (compiling & linking) is a common thing, but
Makefiles are good for other automated build tasks.
- variables: compiler (gcc) and compiler flags (CFLAGS).
- Wall=warnings (display) all
- default target (all)
- To build the file (target),
we need file (dependencies)
- macro replace.flags.
- macro replace for target. macro replace for dependencies
- clean target. remove binaries (and intermediaries if they exist).
Commands:
Write a program that takes in a single, positive integer as a command line
argument,and then writes the numbers 0 through to that number on stdout.
Exercise 3: Loops.c
#include <stdio.h>#include<stdlib.h>
int main(){ int number; number = atoi(argv[1]);
int i = 0; /* do - while */ do { printf("%d\n", i); i++; } while (i <= number);
i = 0; /* while */ while (i <= number) printf("%d\n", i++);
/* for */ for(i = 0; i <= number; i++) printf("%d\n", i);
return 0;}
Add error handling to the Fibonacci.c program so that when the user passes a non-
negative integer in the command line, the program terminates with an exit status of
1.
Modify Fibonacci.c to Fibonacci2.c such that the program prints all the numbers of
Fibonacci series toward the given number.
Write a non-recursive version of the Fibonacci2.c program.
Exercises for home
Programming in C - Part 2
● Pointers
● Typecasting
Pointers
A pointer is a variable whose value is the address of another variable, i.e., direct
address of the memory location.
- same width as long primitive type
- 4 bytes wide (32 bit arch).
- 8 bytes wide (64 bit arch)
- some esoteric architectures have other widths (don’t worry about them)
Declaration
Pointers can point to other pointer types (ad infinitum)
Pointers - Basic Usage
Assignment
You can modify the value of the pointer (the address it’s holding) like a normal
variable.
Referencing
Retrieves the address of a variable. (reverse operation as dereferencing)
Dereferencing
Dereferencing a pointer retrieves the value stored at the memory address held by
that pointer.
Indexing
- notation for indexing.
- when operating on pointers, the square brackets dereference the pointer and then
indexes into the memory referenced
- each index advances the same number of bytes as the size of the pointer type
Example
Pointers - Indexing
Pointers - Example 1 - pointers.c
#include <stdio.h>
int main () { int var = 20; /* actual variable declaration */ int *ip; /* pointer variable declaration */
ip = &var; /* store address of var in pointer variable*/
printf("Address of var variable: %p\n", (void *) &var ); printf("Address stored in ip variable: %p\n", (void *) ip ); printf("Value of *ip variable: %d\n", *ip );
return 0;}
Pointers - Multiple Dereferencing Multiple Dereferencing
You can stack dereference operators to obtain the value of nested pointers.
Although you can stack the dereference operator, you CANNOT stack the reference
operator…
Example
Null Pointers The NULL pointer is a constant with a value of zero defined in several standard
libraries.
It is always a good practice to assign a NULL value to a pointer variable if you do not
have an exact address to be assigned yet.
To check for a null pointer, you can use an 'if' statement as follows:
//nullpointer.c#include <stdio.h>
int main () { int *ptr = NULL; printf("The value of ptr is : %p\n", (void *) ptr ); return 0;}
Passing a Pointer to a FunctionC does not support pass by reference. But you can use pointers to change the value of
a parameter inside a function.
//pointer-param.c#include <stdio.h>
void f(int *j) { (*j)++;}
int main() { int i = 20; f(&i); printf("i = %d\n", i);
int *p = &i; f(p); printf("i = %d\n", i);
return 0;}
Pointer ArithmeticIncrementing a Pointer: ++
In dynamic arrays, we use a pointer to point to the beginning of the array.
Incrementing the pointer to array moves to the next item in the array.
#include <stdio.h>const int MAX = 3;
int main () { int var[] = {10, 100, 200}; int i, *ptr;
/* let us have array address in pointer */ ptr = var;
for ( i = 0; i < MAX; i++) { printf("Address of var[%d] = %p\n", i, (void *) ptr ); printf("Value of var[%d] = %d\n", i, *ptr );
/* move to the next location */ ptr++; } return 0;}
Pointer ArithmeticDecrementing a Pointer: --
Decrementing the pointer to array moves to the previous item in the array.
#include <stdio.h>const int MAX = 3;
int main () { int var[] = {10, 100, 200}; int i, *ptr;
/* let us have array address in pointer */ ptr = &var[MAX-1];
for ( i = MAX; i > 0; i--) { printf("Address of var[%d] = %p\n", i, (void *) ptr ); printf("Value of var[%d] = %d\n", i, *ptr );
/* move to the previous location */ ptr--; } return 0;}
Pointers to structs
Struct Pointers
Function Pointers
Function pointers need more information than just the address of the function, they
need the signature of the function (ret value, parameters) so the compiler can emit
the correct assembly instructions.
Declaration
Usage
Initializing a Function Pointer
//func-pointer.c#include <stdio.h>
void my_int_func(int x){ printf( "%d\n", x );}
int main(){ void (*foo)(int); /* the ampersand is actually optional */ foo = &my_int_func; foo(2); return 0;}
Using a Function Pointer
//funcp-use.c#include <stdio.h>void my_int_func(int x){ printf( "%d\n", x );}
int main(){ void (*foo)(int); foo = &my_int_func;
/* call my_int_func (note that you do not need to write (*foo)(2) ) */ foo( 2 ); /* but if you want to, you may */ (*foo)( 2 );
return 0;}
Passing a Function Pointer //funcp-pass.c#include <stdio.h>void my_int_func(int x){ printf( "%d\n", x );}
void run_my_func(void (*myfunc)(int), int param){ myfunc(param);}
int main(){ void (*foo)(int); foo = &my_int_func;
/* pass my_int_func to run_my_func */ run_my_func(foo, 2);
return 0;}
Typecasting
Typecasting allows us to tell the compiler how we want it to interpret the data.
- type information implies how to read, write and manipulate that type of data
- dictates the effect of operations on the data
Examples
- char and int pointers increment at different rates
- signedness
0x70 + 0x70 = 0xD0 = 208 (signed char)
0x70 + 0x70 = 0xD0 = -32 (unsigned char)
- casting to smaller size data type truncates result.
- casting to larger size data type pads the remaining bytes depending on the data
type. (preserve the value of the data)
- Unsigned pad the higher bits with zeros.
- Signed: sign extend (pad with zeros or 1s depending on MSb of data type
being expanded )
Typecasting
Padding & Truncation Unsigned
Effect of casting between different sized types on memory
Typecasting
Padding & Truncation Signed (A)
Effect of casting between different sized types on memory
Typecasting
Padding & Truncation Signed (B)
Effect of casting between different sized types on memory
Typecasting - Pointers
Pointers
- can typecast pointers as well.
- commonly needed for allocation routines which return type
Example
-
Further Reading
Interactive C programming exercises (highly recommended)
http://www.learn-c.org/en/
C Programming Language
http://www.amazon.ca/C-Programming-Language-2nd-Edition/dp/0131103628
(I’m sure you can find a pdf of this online for free)