0% found this document useful (0 votes)
79 views63 pages

Spring 2013: CSE2421 Systems1

The document discusses linked lists and their implementation. It begins by defining a linked list as a dynamic data structure composed of nodes that together represent a sequence. Each node contains a data element and a pointer to the next node. This allows efficient insertion/deletion from any position. It then provides the structure of a basic linked list node containing an integer data field and a pointer to the next node. Examples are given to build a sample linked list containing the elements 1, 2, 3. Common linked list operations like insertion, deletion, and traversal are described along with pictorial representations. Finally, double linked lists are introduced, which include pointers to both the next and previous nodes.

Uploaded by

Roni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
79 views63 pages

Spring 2013: CSE2421 Systems1

The document discusses linked lists and their implementation. It begins by defining a linked list as a dynamic data structure composed of nodes that together represent a sequence. Each node contains a data element and a pointer to the next node. This allows efficient insertion/deletion from any position. It then provides the structure of a basic linked list node containing an integer data field and a pointer to the next node. Examples are given to build a sample linked list containing the elements 1, 2, 3. Common linked list operations like insertion, deletion, and traversal are described along with pictorial representations. Finally, double linked lists are introduced, which include pointers to both the next and previous nodes.

Uploaded by

Roni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

Spring 2013

CSE2421 Systems1
Introduction to Low-Level Programming and Computer Organization

Kitty Reeves
TWRF 8:00-8:55am

1
Linked List Node structure
A linked list is…
a dynamic data structure consisting of a group of nodes which
together represent a sequence and whose length can be increased
or decreased at run time
Simply, each node is composed of a data and a reference (in other
words, a link) to the next node in the sequence
Allows for efficient insertion or removal of elements from any
position in the sequence (vs an array).
Data items need not be stored contiguously in memory
Major Disadvantage:
does not allow random access to the data or any form of efficient
indexing

/* Node Structure */
struct node { A linked list whose nodes contain two fields: an
int data; integer value and a link to the next node. The last
node is linked to a terminator used to signify the end
struct node *next; }
of the list.
2
Linked List stack and heap
Each node is allocated in the heap with a call to malloc(), so the node
memory continues to exist until it is explicitly deallocated with a call to
free().

3
Build {1,2,3} linked list
/* Build the list {1, 2, 3} in the heap and store its head pointer in a local stack
variable. Returns the head pointer to the caller. */
struct node* BuildOneTwoThree() {
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
// allocate 3 nodes in the heap
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1; // setup first node
head->next = second; // note: pointer assignment rule
second->data = 2; // setup second node
second->next = third;
third->data = 3; // setup third link
third->next = NULL;
// At this point, the linked list referenced by "head“ matches the list in the drawing.
return head; }
4
Linked List example
#include<stdlib.h>
#include<stdio.h>
What does this do?
struct list_el {
int val;
struct list_el * next; };
typedef struct list_el item;
void main() {
item * curr, * head;
int i;
head = NULL;
for(i=1;i<=10;i++) {
curr = (item *) malloc(sizeof(item));
curr->val = i;
curr->next = head;
head = curr; }
curr = head;
while(curr) {
printf("%d\n", curr->val);
curr = curr->next ; }
}
5
Linked list basics
The first node is always made accessible through a
global ‘head’ pointer.
This pointer is adjusted when first node is deleted.
Similarly there can be an ‘end’ pointer that contains
the last node in the list.
This is also adjusted when last node is deleted.
The last node in a list always has a NULL value so you
don’t *have* to keep track of the end of the list, just
check for a NULL pointer.
Whenever a node is added to linked list, it is always
checked if the linked list is empty then add it as the
first node.
You can pass the list by passing the head pointer.

6
Linked List setup
ptr end (optional)
NODE structure
head data data data data
next next next next=NULL

NEED TO:
Allocate a new node structure with DMA
(dynamic memory allocation) new

Add information to data section data


next

7
Linked List ADD/DELETE node
OPERATION FRONT END MIDDLE
new->next = head ptr->next = new new->next = ptr->next
INSERT
head = new new->next = NULL ptr-> next= new

found = false;
ptr = head;
while(ptr != NULL) //what if nothing in list?
SEARCH
{ if(ptr->data = = val) // found what searching for
{ found = true;
break; }
else { ptr = ptr->next; }
} // if found still false, didn’t find

//if ptr->next=NULL
DELETE head = ptr->next prev = ptr prev->next = ptr->next
(fyi: free ptr) // what if only node?
prev->next = NULL
8
Link list pictorial view - INSERT
Inserting into a link list has
two cases
First in the list
Not first in the list
If going at head, modify head
reference (only)
If going elsewhere, need
reference to node before
insertion point
New node.next = cur
node.next
Cur node.next = ref to new
node
Must be done in this order!
9
Link list pictorial view - DELETE
Deleting a link list has two
cases
First in the list
Not first in the list
If deleting from head,
modify head reference
(only)
If deleting elsewhere,
simply “point around” the
deleted node
Be sure to free the deleted
nodes
10
Link list pictorial view - TRAVERSE
Start at the head
Use a “current” reference for
the current node
Use the “next” reference to
find the next node in the list
Repeat this to find the
desired node
N times to find the nth node
Until the object matches if
looking for a particular object
 Caution: objects can “match”
even if the references aren’t the
same…
Don’t forget to check to see if
this is the last node
11
Linked List operations
Initialize the list void InitList(struct list *sList);
Push/Insert a value onto the list
Search the list /* Initializes the list structure */
Pop/Remove a value off of the list void InitList(struct list *sList) {
Print the list sList->start = NULL; }

void push(struct list *sList, int data); void pop(struct list *sList)

/* Adds a value to the front of the list */ /* Removes the first value of the list */
void push(struct list *sList, int data) { void pop(struct list *sList) {
struct node *p; if(sList->start != NULL) {
p = malloc(sizeof(struct node)); struct node *p = sList->start;
p->data = data; sList->start = sList->start->next;
p->next = sList->start; free(p); } }
sList->start = p; }

(see linklst2.c)
12
Double Linked List (DLL)
A more sophisticated form of a
linked list data structure.
Each node contains a value, a
link to the next node (if any)
and a link to the previous node
(if any)
The header points to the first
node in the list and to the last
node in the list (or contains null
links if the list is empty
myDLL
a b c

13
DLLs compared to SLLs
Advantages:
Can be traversed in either direction (may be
essential for some programs)
Some operations, such as deletion and inserting
before a node, become easier
Disadvantages:
Requires more space
List manipulations are slower (because more
links must be changed)
Greater chance of having bugs (because more
links must be manipulated)
14
Double linked list – INSERT
As with singly linked lists,
special case for head
Also special case for tail
Need to update two nodes
Node before new node
Node after new node
Hook up new node before
modifying other nodes
Don’t overwrite necessary
information before relocating it!
Head & tail: if a link is null,
update the head or tail as
appropriate
15
Deleting a node from a DLL
Node deletion from a DLL involves changing two
links
In this example,we will delete node b
myDLL

a b c

Deletion of the first node or the last node is a


special case

16
Double linked list - DELETE
As with singly linked lists,
special case for head
Also special case for tail
Need to update two nodes
Node before new node
Node after new node
Hook up new node before
modifying other nodes
Don’t overwrite necessary
information before relocating
it!
Head & tail: if a link is null,
update the head or tail as
appropriate
17
Other operations on linked lists
Most “algorithms” on linked lists—such as
insertion, deletion, and searching—are pretty
obvious; you just need to be careful
Sorting a linked list is just messy, since you
can’t directly access the nth element—you
have to count your way through a lot of other
elements

18
Double linked lists - SETUP
//DECLARATIONS /* The following function initializes
the linked list by putting zeros into
/* The type link_t needs to be forward- the pointers containing the first and
declared in order that a self-reference last links of the linked list. */
can be made in "struct link" below. */ static void
typedef struct link link_t; linked_list_init (linked_list_t * list)
{ list->first = list->last = 0; }
/* A link_t contains one of the links of
the linked list. */
struct link {
const void * data;
link_t * prev;
link_t * next; };

/* linked_list_t contains a linked list. */


typedef struct linked_list {
link_t * first;
link_t * last; } linked_list_t;
19
Double linked lists - ADD
/* The following function adds a new link to the end of the linked list. It allocates
memory for it. The contents of the link are copied from "data". */
static void
linked_list_add (linked_list_t * list, void * data){
link_t * link;
link = calloc (1, sizeof (link_t)); /* calloc sets the "next" field to zero. */
if (! link) {
fprintf (stderr, "calloc failed.\n");
exit (EXIT_FAILURE); }
link->data = data;
if (list->last) { /* Join the two final links together. */
list->last->next = link;
link->prev = list->last;
list->last = link; }
else {
list->first = link;
list->last = link; }}
20
static void
linked_list_delete (linked_list_t * list, link_t * link) {
link_t * prev;
link_t * next;
Both the previous and
Double prev = link->prev;
next links are valid, so just
bypass “link” without
next = link->next; altering “list” at all
linked if (prev) {
if (next) {
Only the previous link is
lists - prev->next = next;
next->prev = prev; }
valid, so "prev" is now the
last link in "list".
DELETE else {
prev->next = 0;
list->last = prev; } }
else { Only the next link is valid,
if (next) { not th eprevious one, so
“next” is now the first link
next->prev = 0;
in the “list”
list->first = next; }
else {
Neither previous not next
list->first = 0;
links are valid, so the list is
list->last = 0; } } now empty
free (link); }
21
Double linked lists - FREE
/* Free the list's memory. */ s
tatic void
linked_list_free (linked_list_t * list)
{
link_t * link;
link_t * next;
for (link = list->first; link; link = next)
{
/* Store the next value so that we
don't access freed memory. */
next = link->next;
free (link);
}
}

22
Bitwise Operations
Many situations need to operate on the bits
of a data word –
 Register inputs or outputs
 Controlling attached devices
 Obtaining status
Corresponding bits of both operands are
combined by the usual logic operations.
Apply to all kinds of integer types
Signed and unsigned
char, short, int, long, long long
23
Bitwise Operations (cont)
• & – AND • ~ – Complement
• Result is 1 if both • Each bit is reversed
operand bits are 1
• | – OR • << – Shift left
• Result is 1 if either • Multiply by 2
operand bit is 1
• ^ – Exclusive OR • >> – Shift right
• Result is 1 if operand • Divide by 2
bits are different

24
Examples
a 1 1 1 1 0 0 0 0 NOTE: when signed  all the same
FYI: integers are really 32 bits so what is the “real” value?
b 1 0 1 0 1 0 1 0 ~a has preceding 1’s and a<<2 is 0x 3c0

unsigned int c, a, b;
c = a & b; // 1010 0000
c = a | b; // 1111 1010
c = a ^ b; // 0101 1010
c = ~a // 0000 1111
c = a << 2; // 1100 0000
c = a >> 3; // 0001 1110

25
Bitwise AND/OR
char x = ‘A’; char y = ‘a’;
tolower(x) returns ‘a’… HOW? toupper(y) returns ‘A’… HOW?
‘A’ = 0x41 = 0100 0001
‘a’ = 0x61 = 0110 0001
“mask” = 0010 0000 “mask” = 1101 1111
Use OR Use AND

‘A’ = 0100 0001 ‘a’ = 0110 0001


mask = 0010 0000 | mask = 1101 1111 &
‘a’ 0110 0001 ‘A’ 0100 0001

Notice the masks are complements of each other


TRY: char digit to a numeric digit
26
Bitwise XOR
The bitwise XOR may be used to invert selected
bits in a register (toggle)
XOR as a short-cut to setting the value of a
register to zero

0100 0010
0000 1010 XOR (toggle)
0100 1000

27
Bitwise left/right shifts
Possible overflow issues
Exact behavior is implementation dependent
When you shift left by k bits ==
multiplying by 2K

When you shift right by k bits ==


dividing by 2K

*** If it's signed, then it's***


implementation dependent.

28
Bitwise right shifts
a 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 b 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

unsigned int c, a;
c = a >> 3; c 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0

signed int c, a, b;
c = b >> 3; c0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
c = a >> 3; c 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0

EXAMPLE: 8-bit instruction format


101 01000 // ADD 8  ALU adds ACC reg to value at address 8
To get just the instruction i.e. 101… shift right by 5
To get just the address i.e. 01001… shift left by 3, then right by 3

29
C example…
#include <stdio.h>
void main()
{
signed int c, d, a, b, e, f; Output is:
a = 0xF0F0;
b = 0x5555; b >> 3 is aaa
e = 0b01000001;
f = 'A'; a >> 3 is 1e1e
c = b >> 3;
binary = 41
d = a >> 3; char a = A
printf("b >> 3 is %x\n",c);
printf("a >> 3 is %x\n",d);
printf("binary = %x\n",e);
printf("char a = %c",f);
}
30
Bit example exceptions
#include <stdio.h> % gcc -o bitex bitex.c
void main() bitex.c: In function ‘main’:
bitex.c:11: warning: right shift count >= width of type
{ int a, b, c, d, e, f; bitex.c:12: warning: right shift count is negative
a = 0xF0F0F0F0; bitex.c:21: warning: left shift count >= width of type
b = 0x55555555; bitex.c:22: warning: left shift count is negative
c = a >> 3; // repeats sign bit of 1
d = b >> 3; // repeats sign bit of 0
e = a >> 35; // 35(k) % 32(w) but technically undefined
f = b >> -3; // 32(w) - 3(k) but technically undefined % bitex
printf("a >> 3 is %.8x\n",c); a >> 3 is fe1e1e1e
printf("b >> 3 is %.8x\n",d); b >> 3 is 0aaaaaaa
printf("a >> 35 is %.8x\n",e); a >> 35 is fe1e1e1e
printf("b >> -3 is %.8x\n",f); b >> -3 is 00000002
printf("a << 3 is %.8x\n",a << 3); a << 3 is 87878780
printf("b << 3 is %.8x\n",b << 3); b << 3 is aaaaaaa8
printf("a << 35 is %.8x\n",a << 35); a << 35 is 87878780
printf("b << -3 is %.8x\n",b << -3); b << -3 is a0000000
}
31
Traditional Bit Definition
8-bit Printer Status Register

#define EMPTY 01
#define JAM 02
#define LOW_INK 16
#define CLEAN 64

char status;
if (status == (EMPTY | JAM)) ...;
if (status == EMPTY || status == JAM) ...;
while (! status & LOW_INK) ...;

int flags |= CLEAN /* turns on CLEAN bit */


int flags &= ~JAM /* turns off JAM bit */

32
Traditional Bit Definitions
Used very widely in C
 Including a lot of existing code
No checking
 You are on your own to be sure the right bits are set
Machine dependent
 Need to know bit order in bytes, byte order in words
Integer fields within a register
 Need to AND and shift to extract
 Need to shift and OR to insert

33
Int main(with arguments)
Options:
int main(void);
int main();
int main(int argc, char **argv);
int main(int argc, char *argv[]);

The parameters given on a command line are passed to a C


program with two predefined variables
The count of the command-line arguments in argc
The individual arguments as a character strings in the pointer array
argv
The names of argc and argv may be any valid identifier in C, but it is
common convention to use these names
But wait… There is no guarantee that the strings are stored as a
contiguous group (per normal arrays)

34
int main(argc, *arv[])
The name of the program, argv[0], may be useful
when printing diagnostic messages
The individual values of the parameters can be
accessed:
*argv[] also seen as **argv
argc argv
4 myFilt\0

p1\0

p2\0

p3\0
Array of pointers where each
element is a pointer to a character …
35
Command Line Arguments
It is guaranteed that argc is non-negative and
that argv[argc] is a null pointer.
By convention, the command-line arguments
specified by argc and argv include the name of
the program as the first element if argc is greater
than 0
For example, if a user types a command of "rm
file", the shell will initialize the rm process with
argc = 2 and argv = ["rm", "file", NULL]
The main() function is special; normally every C
program must define it exactly once.

36
CLA - Example 1
#include <stdio.h>
int main(int argc, char *argv[]) {
if ( argc != 3)
printf("Usage:\n %s Integer1 Integer2\n",argv[0]);
else
// ascii to integer
printf("%s + %s = %d\n",argv[1],argv[2], atoi(argv[1])+atoi(argv[2]));
return 0;
}

37
CLA – Example 2
#include <stdio.h> Rewrite the
#include <stdlib.h> program which
main( int argc, char *argv[]) copies files, ie,
{ FILE *in_file, *out_file, *fopen(); FCOPY.C to accept
int c; the source and
if( argc != 3 ) { destination
printf("Incorrect, format is FCOPY source dest\n"); filenames from the
exit(2); } command line.
in_file = fopen( argv[1], "r"); Include a check on
if( in_file == NULL ) the number of
printf("Cannot open %s for reading\n", argv[1]); arguments passed.
else { out_file = fopen( argv[2], "w");
if ( out_file == NULL )
printf("Cannot open %s for writing\n", argv[2]);
else { printf("File copy program, copying %s to %s\n", argv[1], argv[2]);
while ( (c=getc( in_file) ) != EOF )
putc( c, out_file );
putc( c, out_file); /* copy EOF */
printf("File has been copied.\n"); fclose( out_file); } fclose( in_file); } }
38
Redirection File I/O
Part of the operating system (linux)
% lab2p2file < lab2p2in >! lab2p2out
! overwrites if the file already exists
input = 0; Input File:
War_Eagle!
scanf(…, input); How_many_WORDS_workhere?
while (input != 0) i
{ loop stuff… $hake_u_r_booty:)_!
Og_sbuCk!!!
input = 0; REALLy_really_really_really___really_long??!!_
scanf(…, input); Hi.01234_How_R_U_?
} |

39
Header and Makefile example

Start here

40
What is happening?
The -c option on the gcc command only
compiles the files listed
Once all 3 C files are correctly compiled, then
using gcc with the -o option allows object
files (notice the .o extensions) to be merged
into one executable file.
Notice where all “mkfunc.h” is included

41
Library includes
The compiler supports two different types of
#includes
Library files
Local files

#include <filename>
#include “filename”

By convention, the names of the standard library


header files end with a .h suffix
Where?  /usr/include

42
Creating header files
In our case, be sure to save your header file in a
‘directory where you are going to save the program’
(NOTE: This is important. Both the header file and the
program must be in the same directory, if not the
program will not be able to detect your header file ).

The header file cannot be included by


#include <headerfilename.h>

The only way to include the header file is to treat the


filename in the same way you treat a string.
#include “headerfilename.h”

43
Makefile Overview
Makefiles are a UNIX thing, not a programming language thing
Makefiles contain UNIX commands and will run them in a specified
sequence.
You name of your makefile has to be: makefile or Makefile
The directory you put the makefile in matters!
You can only have one makefile per directory.
Anything that can be entered at the UNIX command prompt can
be in the makefile.
Each command must be preceded by a TAB and is immediately
followed by hitting the enter key
MAKEFILES ARE UNFORGIVING WHEN IT COMES TO WHITESPACE!
To execute… must be in the directory where the makefile is:
% make tag-name (also called section name)

44
Makefile Details
Compiling our example would look like:
gcc -o mkhello mkmain.c mkhello.c mkfact.c
OR
gcc mkmain.c mkhello.c mkfact.c -o mkhello

The basic makefile is composed of lines:


target: dependencies [tab] system command
“all” is the default target for makefiles
 all: gcc -o mkhello mkmain.c mkhello.c mkfact.c
The make utility will execute this target, “all”, if no
other one is specified.

45
Makefile dependencies
Useful to use different targets
Because if you modify a single project, you don’t have to
recompile everything, only what you modified

In the class example of the makefile:


All has only dependencies, no system commands
If order for make to execute correctly, it has to meet all
the dependencies of the called target (i.e. in this case all)
Each of the dependencies are searched through all the
targets available and executed if found.
make clean
 Fast way to get rid of all the object and executable files (to free
disk space)
 -f do not prompt
 -r remove directories and their contents recursively

46
Why use OOP in general?
The concepts and rules used in object-oriented
programming provide these important benefits:
The concept of data classes allows a programmer to create any
new data type that is not already defined in the language itself
(typedef).
The concept of a data class makes it possible to define
subclasses of data objects that share some or all of the main
class characteristics. Called inheritance, this property of OOP
forces a more thorough data analysis, reduces development
time, and ensures more accurate coding.
Since a class defines only the data it needs to be concerned
with, when an instance of that class (an object) is run, the
code will not be able to accidentally access other program
data. This characteristic of data hiding (i.e. encapsulation)
provides greater system security and avoids unintended data
corruption.

47
WHY use OOP in general (cont)?
Facilitates utilizing and creating reusable
software components
The definition of a class is reuseable not only by the
program for which it is initially created but also by other
object-oriented programs (and, for this reason, can be
more easily distributed for use in networks).
Better suited for team development
Easier software maintenance

48
OOP simple review
• Class
• A software construct that abstractly models something
• Defines a structure to hold some sort of state
• Defines operations that mutate or recall this state
somehow
• Object
• A specific instance of a Class
• Holds the state representing a particular instance of the
Class
• Examples:
• Class – Person
• Instance – William Gates

49
OOP simple review (cont)
Define method (~function)
To emulate member functions, you can put function pointers
in structs.
Define inheritance
a way to reuse code of existing objects, or to establish a
subtype from an existing object, or both, depending upon
programming language support
Define polymorphism
the ability to create a variable, a function, or an object that has
more than one form
allows values of different data types to be handled using a
uniform interface (malloc returns void type)
Encapsulation == information hiding
C has language support for private encapsulation of both
variables and functions, through the static keyword

50
Porting object-oriented concepts to C
It's possible to create object-oriented like code in C, which
is very useful for mimicking standard libraries and objects
found in OOPs
Ex. Stack and Queue classes with push/pop methods =
functions - the basis for modular structured programming in C.
Header files = Use to define global constants and variables
Take a class design from what would be standard OOP,
retain strictly only member variables, and move them to a
struct.
Within global space, create functions that take a pointer to
a related struct instance and manipulate accordingly. For
every instance of the object, only use the related functions
instead of directly accessing the data. This is to mimic the
data hiding found in OOPs.

51
Features of OOC
Encapsulation and data hiding (can be achieved using
structs/opaque pointers)
Inheritance and support for polymorphism (single inheritance can
be achieved using structs - make sure abstract base is not
instantiable)
Constructor and destructor functionality (not easy to achieve)
Type checking (at least for user defined types as C doesn't enforce
any)
Instead of passing pointers to structs, you end up passing pointers
to pointers to structs. This makes the content opaque and
facilitates polymorphism and inheritance. The real problem with
OOP in C is what happens when variables exit scope. There's no
compiler generated destructors and that can cause issues.
MACROS can possibly help but it is always going to be ugly to look
at.

52
Class
The basic idea of implementing a class in C is
to group the data for a C object into structs so
that you can have any number of objects. The
struct is declared in the .h file so that it is
shared between the class and its clients. In
addition, you usually need a function that
initializes the objects in the class.

53
Methods
If you think of methods called on objects as
static methods that pass an implicit 'this' into
the function it can make thinking OO in C
easier.
For example:
String s = "hi";
System.out.println(s.length());
becomes:
string s = "hi";
printf(length(s)); // pass in s, as an implicit this

54
Objects
At the most basic level, you just use plain structs
as objects and pass them around by pointers.
struct monkey
{
float age;
bool is_male;
int happiness;
};

void monkey_dance(struct monkey *monkey)


{
/* do a little dance */
}

55
Opaque Pointers
An opaque pointer is a special case of an opaque data type, a data
type declared to be a pointer to a record or data structure of some
unspecified type.
Opaque pointers are a way to hide the implementation details of
an interface from ordinary clients, so that the implementation may
be changed without the need to recompile the modules using it.
This benefits the programmer as well since a simple interface can
be created, and most details can be hidden in another file.
This example demonstrates a way to achieve the information
hiding (encapsulation) aspect of Object-Oriented Programming
using the C language. If someone wanted to change the
declaration of struct obj, it would be unnecessary to recompile any
other modules in the program that use the obj.h header file unless
the API was also changed.
56
Opaque /* obj.c */
Pointer #include "obj.h"
struct obj {
example int id; };

/* The caller will handle allocation.


/* obj.h */ Provide the required information only */

struct obj; size_t obj_size(void)


{ return sizeof(struct obj); }
/* The compiler considers struct
obj an incomplete type. int obj_setid(struct obj *o, int i)
Incomplete types can be used in { if (o == NULL) return -1;
declarations. */ o->id = i;
return 0; }
size_t obj_size(void);
int obj_setid(struct obj *, int); int obj_getid(struct obj *o, int *i)
int obj_getid(struct obj *, int *); { if (o == NULL) return -1;
*i = o->id;
return 0; }
57
Opaque Pointer example
The crux of the matter is to separate declaration from definition just like
we were always told In the example of the fibheap, we want the user to
have a handle to the fibheap but to otherwise not be able to affect the
heap except through the API functions. So, we do this
/* FILE: fibheap.h */
typedef struct FibHeap FibHeap;
FibHeapElement *fibHeapGetRoot(FibHeap*);
int fibHeapGetSize(FibHeap*);
And that’s it. There is no definition of the structure here, only a
declaration of it. Then:
/* FILE: fibheap.c */
struct FibHeap {
FibHeapElement *root;
unsigned int size; };
Because only the declaration is in the header, whenever the user does
#include "fibheap.h" he only gets the name of the struct, not the layout.
Thus the user cannot access either of the fields without the accessor
functions:
fibHeapGetRoot(FibHeap*)
fibHeapGetSize(FibHeap*)
58
Virtual Tables in C (vtables)
A virtual table, or "vtable", is a mechanism used
in Programming languages to support dynamic
polymorphism, i.e., run-time method binding.
A more in-depth answer...
Each function has an address in memory
somewhere. Function names are just pretty ways of
referring to a position in memory. When a program is
linked (after the compiler is finished compiling) all
those names are replaced with hardcoded memory
addresses.

59
Vtables and polymorphism
You can implement polymorphism with regular
functions and virtual tables (vtables)

60
Inheritance
To get things like inheritance You can do manual
and polymorphism, you have inheritance by
to work a little harder. having the first
member of a
struct base structure be an
{ instance of the
/* base class members */
}; superclass, and
struct derived then you can cast
{ around pointers to
struct base super; base and derive
/* derived class members */ classes freely
};
struct derived d;
struct base *base_ptr = (struct base *)&d; // upcast
struct derived derived_ptr = (struct derived *)base_ptr; // downcast
61
Define object then inherit
Each object has its own file.
Public functions and variables are defined in the .h file for an object.
Private variables and functions were only located in the .c file.
To "inherit“, a new struct is created with the first member of the struct
being the object to inherit from.
Inheriting is difficult to describe, but basically it was this:
struct vehicle { int power; int weight; }
Then in another file:
struct van { struct vehicle base; int cubic_size; }
Then you could have a van created in memory, and being used by code
that only knew about vehicles:
struct van my_van;
struct vehicle *something = &my_van;
vehicle_function( something );
It worked beautifully, and the .h files defined exactly what you should be
able to do with each object.

62
OOC Example
#include "triangle.h" Output:
#include "rectangle.h" 6.56 This is real, pure C, no preprocessor
#include "polygon.h" 13.12 macros. We have inheritance,
#include <stdio.h> polymorphism and data
encapsulation (including data
private to classes or objects). There
int main() { is no chance for protected qualifier
Triangle tr1= CTriangle->new(); equivalent, that is, private data is
Rectangle rc1= CRectangle->new(); private down the inheritance chain
too; but not an inconvenience
because not necessary.
tr1->width= rc1->width= 3.2;
tr1->height= rc1->height= 4.1;
CPolygon is not instantiated because
CPolygon->printArea((Polygon)tr1); we only use it to manipulate objects
of down the innheritance chain that
have common aspects but different
printf("\n"); implementation of them
(Polymorphism)
CPolygon->printArea((Polygon)rc1); }
63

You might also like