Object Oriented Programming Lab

Thursday, December 3, 2009.
Brief Introduction to the C Programming Language



Object Oriented Programming Lab



Introduction

* The C programming language was designed by Dennis Ritchie at Bell Laboratories in the early 1970s
* Influenced by
o ALGOL 60 (1960),
o CPL (Cambridge, 1963),
o BCPL (Martin Richard, 1967),
o B (Ken Thompson, 1970)
* Traditionally used for systems programming, though this may be changing in favor of C++
* Traditional C:
o The C Programming Language, by Brian Kernighan and Dennis Ritchie, 2nd Edition, Prentice Hall
o Referred to as K&R

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Standard C

* Standardized in 1989 by ANSI (American National Standards Institute) known as ANSI C
* International standard (ISO) in 1990 which was adopted by ANSI and is known as C89
* As part of the normal evolution process the standard was updated in 1995 (C95) and 1999 (C99)
* C++ and C
o C++ extends C to include support for Object Oriented Programming and other features that facilitate large software development projects
o C is not strictly a subset of C++, but it is possible to write “Clean C” that conforms to both the C++ and C standards.




Elements of a C Program

* A C development environment includes
o System libraries and headers: a set of standard libraries and their header files. For example see /usr/include and glibc.
o Application Source: application source and header files
o Compiler: converts source to object code for a specific platform
o Linker: resolves external references and produces the executable module
* User program structure
o there must be one main function where execution begins when the program is run. This function is called main
+ int main (void) { ... },
+ int main (int argc, char *argv[]) { ... }
+ UNIX Systems have a 3rd way to define main(), though it is not POSIX.1 compliant
int main (int argc, char *argv[], char *envp[])
o additional local and external functions and variables







A Simple C Program

* Create example file: try.c
* Compile using gcc:
gcc –o try try.c
* The standard C library libc is included automatically
* Execute program
./try
* Note, I always specify an absolute path
* Normal termination:
void exit(int status);
o calls functions registered with atexit()
o flush output streams
o close all open streams
o return status value and control to host environment



/* you generally want to

* include stdio.h and

* stdlib.h

* */

#include

#include

int main (void)

{

printf(“Hello World\n”);

exit(0);

}



Source and Header files

* Just as in C++, place related code within the same module (i.e. file).
* Header files (*.h) export interface definitions
o function prototypes, data types, macros, inline functions and other common declarations
* Do not place source code (i.e. definitions) in the header file with a few exceptions.
o inline’d code
o class definitions
o const definitions
* C preprocessor (cpp) is used to insert common definitions into source files
* There are other cool things you can do with the preprocessor




Another Example C Program

example.c

/* this is a C-style comment

* You generally want to palce

* all file includes at start of file

* */

#include

#include

int

main (int argc, char **argv)

{

// this is a C++-style comment

// printf prototype in stdio.h

printf(“Hello, Prog name = %s\n”,

argv[0]);

exit(0);

}

/* comments */

#ifndef _STDIO_H

#define _STDIO_H

... definitions and protoypes

#endif

/usr/include/stdio.h

/* prevents including file

* contents multiple

* times */

#ifndef _STDLIB_H

#define _STDLIB_H

... definitions and protoypes

#endif

/usr/include/stdlib.h

#include directs the preprocessor

to “include” the contents of the file

at this point in the source file.

#define directs preprocessor to define macros.





Passing Command Line Arguments

* When you execute a program you can include arguments on the command line.
* The run time environment will create an argument vector.
o argv is the argument vector
o argc is the number of arguments
* Argument vector is an array of pointers to strings.
* a string is an array of characters terminated by a binary 0 (NULL or ‘\0’).
* argv[0] is always the program name, so argc is at least 1.




./try –g 2 fred

argc = 4,

argv =

‘t’‘r’‘y’‘\0’

argv:

[0]

[1]

[2]

[3]

[4] NULL

‘-’‘g’‘\0’

‘2’‘\0’

‘f’‘r’‘e’‘d’‘\0’


C Standard Header Files you may want to use

* Standard Headers you should know about:
o stdio.h – file and console (also a file) IO: perror, printf, open, close, read, write, scanf, etc.
o stdlib.h - common utility functions: malloc, calloc, strtol, atoi, etc
o string.h - string and byte manipulation: strlen, strcpy, strcat, memcpy, memset, etc.
o ctype.h – character types: isalnum, isprint, isupport, tolower, etc.
o errno.h – defines errno used for reporting system errors
o math.h – math functions: ceil, exp, floor, sqrt, etc.
o signal.h – signal handling facility: raise, signal, etc
o stdint.h – standard integer: intN_t, uintN_t, etc
o time.h – time related facility: asctime, clock, time_t, etc.



The Preprocessor

* The C preprocessor permits you to define simple macros that are evaluated and expanded prior to compilation.



* Commands begin with a ‘#’. Abbreviated list:
o #define : defines a macro
o #undef : removes a macro definition
o #include : insert text from file
o #if : conditional based on value of expression
o #ifdef : conditional based on whether macro defined
o #ifndef : conditional based on whether macro is not defined
o #else : alternative
o #elif : conditional alternative
o defined() : preprocessor function: 1 if name defined, else 0
#if defined(__NetBSD__)




Preprocessor: Macros

* Using macros as functions, exercise caution:
o flawed example: #define mymult(a,b) a*b
+ Source: k = mymult(i-1, j+5);
+ Post preprocessing: k = i – 1 * j + 5;
o better: #define mymult(a,b) (a)*(b)
+ Source: k = mymult(i-1, j+5);
+ Post preprocessing: k = (i – 1)*(j + 5);
* Be careful of side effects, for example what if we did the following
o Macro: #define mysq(a) (a)*(a)
o flawed usage:
+ Source: k = mysq(i++)
+ Post preprocessing: k = (i++)*(i++)
* Alternative is to use inline’ed functions
o inline int mysq(int a) {return a*a};
o mysq(i++) works as expected in this case.




Preprocessor: Conditional Compilation

* Its generally better to use inline’ed functions
* Typically you will use the preprocessor to define constants, perform conditional code inclusion, include header files or to create shortcuts
* #define DEFAULT_SAMPLES 100
* #ifdef __linux

static inline int64_t
gettime(void) {...}

* #elif defined(sun)

static inline int64_t
gettime(void) {return (int64_t)gethrtime()}

* #else

static inline int64_t
gettime(void) {... gettimeofday()...}

* #endif




Another Simple C Program

int main (int argc, char **argv) {

int i;

printf(“There are %d arguments\n”, argc);

for (i = 0; i < argc; i++) printf(“Arg %d = %s\n”, i, argv[i]); return 0; } * Notice that the syntax is similar to Java * What’s new in the above simple program? o of course you will have to learn the new interfaces and utility functions defined by the C standard and UNIX o Pointers will give you the most trouble Fred Kuhns () CSE332– Object Oriented Programming Lab * A variable declared as an array represents a contiguous region of memory in which the array elements are stored. int x[5]; // an array of 5 4-byte ints. * All arrays begin with an index of 0 * An array identifier is equivalent to a pointer that references the first element of the array o int x[5], *ptr; ptr = &x[0] is equivalent to ptr = x; * Pointer arithmetic and arrays: o int x[5]; x[2] is the same as *(x + 2), the compiler will assume you mean 2 objects beyond element x. Arrays and Pointers 0 1 2 3 4 1 0 2 3 little endian byte ordering memory layout for array x Fred Kuhns () CSE332– Object Oriented Programming Lab Pointers * For any type T, you may form a pointer type to T. o Pointers may reference a function or an object. o The value of a pointer is the address of the corresponding object or function o Examples: int *i; char *x; int (*myfunc)(); * Pointer operators: * dereferences a pointer, & creates a pointer (reference to) o int i = 3; int *j = &i; *j = 4; printf(“i = %d\n”, i); // prints i = 4 o int myfunc (int arg); int (*fptr)(int) = myfunc; i = fptr(4); // same as calling myfunc(4); * Generic pointers: o Traditional C used (char *) o Standard C uses (void *) – these can not be dereferenced or used in pointer arithmetic. So they help to reduce programming errors * Null pointers: use NULL or 0. It is a good idea to always initialize pointers to NULL. Fred Kuhns () CSE332– Object Oriented Programming Lab Pointers in C (and C++) Address 0x3dc 0x3d8 Program Memory 0x3cc 0x3c8 0x3c4 0x3c0 Note: The compiler converts z[1] or *(z+1) to Value at address (Address of z + sizeof(int)); In C you would write the byte address as: (char *)z + sizeof(int); or letting the compiler do the work for you (int *)z + 1; Step 1: int main (int argc, argv) { int x = 4; int *y = &x; int *z[4] = {NULL, NULL, NULL, NULL}; int a[4] = {1, 2, 3, 4}; ... 0x3bc 0x3b8 0x3b4 0x3b0 0x3d4 0x3d0 z[3] z[2] z[1] z[0] a[3] a[2] a[1] a[0] 4 0x3dc 0 0 0 0 4 3 2 1 NA NA x y Fred Kuhns () CSE332– Object Oriented Programming Lab Pointers Continued 4 0x3dc Address 0x3dc 0x3d8 Program Memory 0x3bc 0x3b8 0x3b4 0x3b0 0x3cc 0x3c8 0x3c4 0x3c0 Step 1: int main (int argc, argv) { int x = 4; int *y = &x; int *z[4] = {NULL, NULL, NULL, NULL}; int a[4] = {1, 2, 3, 4}; Step 2: Assign addresses to array Z z[0] = a; // same as &a[0]; z[1] = a + 1; // same as &a[1]; z[2] = a + 2; // same as &a[2]; z[3] = a + 3; // same as &a[3]; 0x3bc 0x3b8 0x3b4 0x3b0 4 3 2 1 NA 0x3d4 0x3d0 z[3] z[2] z[1] z[0] a[3] a[2] a[1] a[0] NA x y Fred Kuhns () CSE332– Object Oriented Programming Lab Pointers Continued 4 0x3dc Address 0x3dc 0x3d8 Program Memory 0x3bc 0x3b8 0x3b4 0x3b0 0x3cc 0x3c8 0x3c4 0x3c0 Step 1: int main (int argc, argv) { int x = 4; int *y = &x; int *z[4] = {NULL, NULL, NULL, NULL}; int a[4] = {1, 2, 3, 4}; Step 2: z[0] = a; z[1] = a + 1; z[2] = a + 2; z[3] = a + 3; Step 3: No change in z’s values z[0] = (int *)((char *)a); z[1] = (int *)((char *)a + sizeof(int)); z[2] = (int *)((char *)a + 2 * sizeof(int)); z[3] = (int *)((char *)a + 3 * sizeof(int)); 0x3bc 0x3b8 0x3b4 0x3b0 4 3 2 1 NA 0x3d4 0x3d0 z[3] z[2] z[1] z[0] a[3] a[2] a[1] a[0] NA x y Fred Kuhns () CSE332– Object Oriented Programming Lab Getting Fancy with Macros #define QNODE(type) \ struct { \ struct type *next; \ struct type **prev; \ } #define QNODE_INIT(node, field) \ do { \ (node)->field.next = (node); \

(node)->field.prev = \

&(node)->field.next; \

} while ( /* */ 0 );

#define QFIRST(head, field) \

((head)->field.next)

#define QNEXT(node, field) \

((node)->field.next)

#define QEMPTY(head, field) \

((head)->field.next == (head))

#define QFOREACH(head, var, field) \

for ((var) = (head)->field.next; \

(var) != (head); \

(var) = (var)->field.next)

#define QINSERT_BEFORE(loc, node, field) \

do { \

*(loc)->field.prev = (node); \

(node)->field.prev = \

(loc)->field.prev; \

(loc)->field.prev = \

&((node)->field.next); \

(node)->field.next = (loc); \

} while (/* */0)

#define QINSERT_AFTER(loc, node, field) \

do { \

((loc)->field.next)->field.prev = \

&(node)->field.next; \

(node)->field.next = (loc)->field.next; \

(loc)->field.next = (node); \

(node)->field.prev = &(loc)->field.next; \

} while ( /* */ 0)

#define QREMOVE(node, field) \

do { \

*((node)->field.prev) = (node)->field.next; \

((node)->field.next)->field.prev = \

(node)->field.prev; \

(node)->field.next = (node); \

(node)->field.prev = &((node)->field.next); \

} while ( /* */ 0)

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



typedef struct wth_t {

int state;

QNODE(wth_t) alist;

} wth_t;


#define QNODE(type) \

struct { \

struct type *next; \

struct type **prev; \

}

After Preprocessing and Compiling

typedef struct wth_t {

int state;

struct {

struct wth_t *next;

struct wth_t **prev;

} alist;

} wth_t;


state

next

prev

3 words in memory

0

0x00100

0x00104

0x100

head: instance of wth_t

0x104

0x108

memory layout after GCC

CPP

QNODE_INIT(head, alist)

#define QNODE_INIT(node, field) \

do { \

(node)->field.next = (node); \

(node)->field.prev = &(node)->field.next;\

} while ( /* */ 0 );

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

QNODE Manipulations

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

?

before

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

0x100

0

0x1a0

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QNODE Manipulations

before


#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

0x100

0

0x1a0

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x104

node0

0x1a4

0x1a8

QNODE Manipulations

before

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x1a0

0x104

node0

0x1a4

0x1a8

QNODE Manipulations

before

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QNODE Manipulations

before



#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next;\

(node)->alist.next = (head); \

} while (/* */0)

0x100

0

0x100

0x104

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node0, alist);

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QNODE Manipulations

before

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Adding a Third Node

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node1, alist);

0x200

0

0x200

0x204

node1

0x204

0x208

#define QINSERT_BEFORE(head, node, alist)\

do { \

*(head)->alist.prev = (node); \

(node)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node)->alist.next; \

(node)->alist.next = (head); \

} while (/* */0)

0x200

0

0x200

0x204

node1

0x204

0x208

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8


Adding a Third Node

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node1, alist);

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x200

0x204

node1

0x204

0x208

#define QINSERT_BEFORE(head, node1, alist)\

do { \

*(head)->alist.prev = (node1); \

(node1)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node1)->alist.next; \

(node1)->alist.next = (head); \

} while (/* */0)

0x200

0

0x200

0x204

node1

0x204

0x208

(1)

(1)


Adding a Third Node

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node1, alist);

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x200

0x204

node1

0x204

0x208

#define QINSERT_BEFORE(head, node1, alist)\

do { \

*(head)->alist.prev = (node1); \

(node1)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node1)->alist.next; \

(node1)->alist.next = (head); \

} while (/* */0)

0x200

0

0x200

0x1a4

node1

0x204

0x208

(1)

(2)

(2)


Adding a Third Node

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node1, alist);

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x200

0x204

node1

0x204

0x208

#define QINSERT_BEFORE(head, node1, alist)\

do { \

*(head)->alist.prev = (node1); \

(node1)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node1)->alist.next; \

(node1)->alist.next = (head); \

} while (/* */0)

0x200

0

0x200

0x1a4

node1

0x204

0x208

(1)

(1)

(2)

(2)

(3)

(3)


Adding a Third Node

0x100

0

0x1a0

0x1a4

head

0x104

0x108

0x1a0

0

0x100

0x104

node0

0x1a4

0x1a8

QINSERT_BEFORE(head, node1, alist);

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x200

0x204

node1

0x204

0x208

#define QINSERT_BEFORE(head, node1, alist)\

do { \

*(head)->alist.prev = (node1); \

(node1)->alist.prev = (head)->alist.prev; \

(head)->alist.prev = &(node1)->alist.next; \

(node1)->alist.next = (head); \

} while (/* */0)

0x200

0

0x100

0x1a4

node1

0x204

0x208

(1)

(1)

(2)

(2)

(3)

(3)

(4)

(4)





Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

0x100

0

??

??

head

0x104

0x108

0x1a0

0

??

??

node0

0x1a4

0x1a8

0x200

0

??

??

node1

0x204

0x208

#define QREMOVE(node, alist) \

do { \

(1) *((node)->alist.prev) = (node)->alist.next; \

(2) ((node)->alist.next)->alist.prev = (node)->alist.prev;\

(3) (node)->alist.next = (node); \

(4) (node)->alist.prev = &((node)->alist.next); \

} while ( /* */ 0)

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

#define QREMOVE(node, alist) \

do { \

*((node)->alist.prev) = (node)->alist.next; \

((node)->alist.next)->alist.prev = (node)->alist.prev;\

(node)->alist.next = (node); \

(node)->alist.prev = &((node)->alist.next); \

} while ( /* */ 0)

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208



0

0x200

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

#define QREMOVE(node0, alist) \

do { \

(1) *((node0)->alist.prev) = (node0)->alist.next; \

((node0)->alist.next)->alist.prev = (node0)->alist.prev;\

(node0)->alist.next = (node0); \

(node0)->alist.prev = &((node0)->alist.next); \

} while ( /* */ 0)

(1)


0x100

0

0x200

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x104

node1

0x204

0x208

Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

#define QREMOVE(node0, alist) \

do { \

*((node0)->alist.prev) = (node0)->alist.next; \

(2) ((node0)->alist.next)->alist.prev = (node0)->alist.prev;\

(node0)->alist.next = (node0); \

(node0)->alist.prev = &((node0)->alist.next); \

} while ( /* */ 0)

(2)




0x100

0

0x200

0x204

head

0x104

0x108

0x1a0

0

0x1a0

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x104

node1

0x204

0x208

Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

#define QREMOVE(node0, alist) \

do { \

*((node0)->alist.prev) = (node0)->alist.next; \

((node0)->alist.next)->alist.prev = (node0)->alist.prev;\

(3) (node0)->alist.next = (node0); \

(node0)->alist.prev = &((node0)->alist.next); \

} while ( /* */ 0)

(3)



0x100

0

0x200

0x204

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

0x200

0

0x100

0x104

node1

0x204

0x208

Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

#define QREMOVE(node0, alist) \

do { \

*((node0)->alist.prev) = (node0)->alist.next; \

((node0)->alist.next)->alist.prev = (node0)->alist.prev;\

(node0)->alist.next = (node0); \

(4) (node0)->alist.prev = &((node0)->alist.next); \

} while ( /* */ 0)

(4)

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Solution to Removing a Node

0x100

0

0x1a0

0x204

head

0x104

0x108

0x1a0

0

0x200

0x104

node0

0x1a4

0x1a8

0x200

0

0x100

0x1a4

node1

0x204

0x208

QREMOVE(node0, alist);

0x100

0

0x200

0x204

head

0x104

0x108

0x1a0

0

0x1a0

0x1a4

node0

0x1a4

0x1a8

0x200

0

0x100

0x104

node1

0x204

0x208

#define QREMOVE(node, alist) \

do { \

(1) *((node)->alist.prev) = (node)->alist.next; \

(2) ((node)->alist.next)->alist.prev = (node)->alist.prev;\

(3) (node)->alist.next = (node); \

(4) (node)->alist.prev = &((node)->alist.next); \

} while ( /* */ 0)



Functions

* Always use function prototypes
int myfunc (char *, int, struct MyStruct *);
int myfunc_noargs (void);
void myfunc_noreturn (int i);
* C and C++ are call by value, copy of parameter passed to function
o C++ permits you to specify pass by reference
o if you want to alter the parameter then pass a pointer to it (or use references in C++)
* If performance is an issue then use inline functions, generally better and safer than using a macro. Common convention
o define prototype and function in header or name.i file
o static inline int myinfunc (int i, int j);
o static inline int myinfunc (int i, int j) { ... }




Basic Types and Operators

* Basic data types
o Types: char, int, float and double
o Qualifiers: short, long, unsigned, signed, const
* Constant: 0x1234, 12, “Some string”
* Enumeration:
o Names in different enumerations must be distinct
o enum WeekDay_t {Mon, Tue, Wed, Thur, Fri};
enum WeekendDay_t {Sat = 0, Sun = 4};
* Arithmetic: +, -, *, /, %
o prefix ++i or --i ; increment/decrement before value is used
o postfix i++, i--; increment/decrement after value is used
* Relational and logical: <, >, <=, >=, ==, !=, &&, ||
* Bitwise: &, |, ^ (xor), <<, >>, ~(ones complement)




Operator Precedence (from “C a Reference Manual”, 5th Edition)

15

16

Precedence

right-to-left

unary

address of

&

right-to-left

unary

indirection

(dereference)

*

right-to-left

unary

negation, plus

- +

right-to-left

unary

logical not

!

right-to-left

unary

bitwise not

~

right-to-left

prefix

increment, decrement

++ --

left-to-right

postfix

compound literal

(type){init}

left-to-right

postfix

increment, decrement

++ --

left-to-right

postfix

direct selection

.

left-to-right

postfix

function call

f(...)

left-to-right

postfix

subscripting

a[k]

size

indirect selection

simple tokens

Operator

n/a

primary

names,
literals

right-to-left

unary

sizeof

left to right

postfix

->

Associates

Class

Tokens

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Precedence

right-to-left

unary

casts

(type)

left-to-right

binary

multiplicative

* / %

left-to-right

binary

additive

+ -

sequential eval.

assignment

conditional

logical or

logical and

bitwise or

bitwise xor

bitwise and

equality/ineq.

relational

left, right shift

Operator

left-to-right

binary

,

right-to-left

binary

= += -=

*= /= %=

&= ^= |=

<<= >>=

right-to-left

ternary

?:

left-to-right

binary

||

left-to-right

binary

&&

left-to-right

binary

|

left-to-right

binary

^

left-to-right

binary

&

left-to-right

binary

== !=

left-to-right

binary

< <= > >=

left-to-right

binary

<< >>

Associates

Class

Tokens




Structs and Unions

* structures
o struct MyPoint {int x, int y};
o typedef struct MyPoint MyPoint_t;
o MyPoint_t point, *ptr;
o point.x = 0;point.y = 10;
o ptr = &point; ptr->x = 12; ptr->y = 40;
* unions
o union MyUnion {int x; MyPoint_t pt; struct {int 3; char c[4]} S;};
o union MyUnion x;
o Can only use one of the elements. Memory will be allocated for the largest element



Conditional Statements (if/else)

if (a < 10) printf(“a is less than 10\n”); else if (a == 10) printf(“a is 10\n”); else printf(“a is greater than 10\n”); * If you have compound statements then use brackets (blocks) o if (a < 4 && b > 10) {
c = a * b; b = 0;
printf(“a = %d, a\’s address = 0x%08x\n”, a, (uint32_t)&a);
} else {
c = a + b; b = a;
}
* These two statements are equivalent:
o if (a) x = 3; else if (b) x = 2; else x = 0;
o if (a) x = 3; else {if (b) x = 2; else x = 0;}
* Is this correct?
o if (a) x = 3; else if (b) x = 2;
else (z) x = 0; else x = -2;



Conditional Statements (switch)

int c = 10;

switch (c) {

case 0:

printf(“c is 0\n”);

break;

...

default:

printf(“Unknown value of c\n”);

break;

}

* What if we leave the break statement out?
* Do we need the final break statement on the default case?

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Loops

* flow control
o break – exit innermost loop
o continue – perform next iteration of loop
* Note, all these forms permit one statement to be executed. By enclosing in brackets we create a block of statements.



for (i = 0; i < MAXVALUE; i++) {
dowork();
}

while (c != 12) {
dowork();
}

do {
dowork();
} while (c < 12);

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Building your program

* For all labs and programming assignments:
o you must supply a make file
o you must supply a README file that describes the assignment and results. This must be a text file, no MS word.
o of course the source code and any other libraries or utility code you used
o you may submit plots, they must be postscript or pdf



make and Makefiles, Overview

* Why use make?
o convenience of only entering compile directives once
o make is smart enough (with your help) to only compile and link modules that have changed or which depend on files that have changed
o allows you to hide platform dependencies
o promotes uniformity
o simplifies my (and hopefully your) life when testing and verifying your code
* A makefile contains a set of rules for building a program
target ... : prerequisites ...
command
...
* Static pattern rules.
o each target is matched against target-pattern to derive stem which is used to determine prereqs (see example)
targets ... : target-pattern : prereq-patterns ...
command
...




Makefiles

* Defining variables
MyOPS := -DWTH
MyDIR ?= /home/fred
MyVar = $(SHELL)
* Using variables
MyFLAGS := $(MyOPS)
* Built-in Variables
o $@ = filename of target
o $< = name of the first prerequisites
* Patterns
o use % character to determine stem
o foo.o matches the pattern %.o with foo as the stem.
o foo.o moo.o : %.o : %.c # says that foo.o depends on foo.c and moo.o depends on moo.c

Fred Kuhns ()

CSE332– Object Oriented Programming Lab



Example Makefile for wulib

# Project specific

include ../Makefile.inc

INCLUDES = ${WUINCLUDES} –I.

LIBS = ${WILIBS} ${OSLIBS}

CFLAGS = ${WUCLFAGS} –DWUDEBUG

CC = ${WUCC}

HDRS := util.h

CSRCS := testapp1.c testapp2.c

SRCS := util.c callout.c

COBJS = $(addprefix ${OBJDIR}/, \

$(patsubst %.c,%.o,$(CSRCS)))

OBJS = $(addprefix ${OBJDIR}/, \

$(patsubst %.c,%.o,$(SRCS)))

CMDS = $(addprefix ${OBJDIR}/, $(basename $(CSRCS)))

all : $(OBJDIR) $(CMDS)

install : all

$(OBJDIR) :

mkdir $(OBJDIR)

$(OBJS) $(COBJS) : ${OBJDIR}/%.o : %.c $(HDRS)

${CC} ${CFLAGS} ${INCLUDES} –o $@ -c $<

$(CMDS) : ${OBJDIR}/% : ${OBJDIR}/%.o $(OBJS)

${CC} ${CFLAGS} -o $@ $@.o ${LIBS}

chmod 0755 $@

clean :

/bin/rm -f $(CMDS) $(OBJS)

# Makefile.inc

# Contains common definitions

MyOS := $(shell uname -s)

MyID := $(shell whoami)

MyHost := $(shell hostname)

WARNSTRICT := -W \

-Wstrict-prototypes \

-Wmissing-prototypes

WARNLIGHT := -Wall

WARN := ${WARNLIGHT}

ALLFLGS := -D_GNU_SOURCE \

-D_REENTRANT \

-D_THREAD_SAFE

APPCFLGS = $(ALLFLGS) \

$(WARN)

WUCC := gcc

WUCFLAGS := -DMyOS=$(MyOS) \

$(OSFLAGS) \

$(ALLFLGS) $(WARN)

WUINCLUDES :=

WULIBS := -lm

ifeq (${MyOS), SunOS)

OSLIBS+= -lrt

endif

Comentários:

 
VIJAYA KUMAR R R © Copyright 2010 | Design By Gothic Darkness |