abstract containers and logic

Click here to load reader

Upload: cate

Post on 22-Feb-2016

45 views

Category:

Documents


0 download

DESCRIPTION

Abstract Containers and Logic. Structures, Unions, Bit Manipulation and Enumerations. Outline. Structures Unions Bit Manipulation Enumerations. Abstract Containers and Logic. Previously we introduced the concept and techniques related to the array data structure. - PowerPoint PPT Presentation

TRANSCRIPT

Array Data Structures & Algorithms

Structures, Unions, Bit Manipulation and EnumerationsAbstract Containers and Logic1OutlineStructuresUnionsBit Manipulation Enumerations

Abstract Containers and LogicPreviously we introduced the concept and techniques related to the array data structure.A collection of identical data typesPermits use of operations defined on the data typesAllocated (logically) contiguous locations in RAMPermits use of relative offset to provide direct access to elements, based on the properties of the data types

This raises the question: Can one create other kinds of (abstract) data structures, and types, in the C language?The answer is Yes !3Abstract Containers - structFirst we consider an abstract data structure thatContains different data typesPermits use of operations appropriate to each typeAllocates memory in a way that supports direct access to elementsSupports user defined abstract data types and containers

The C language struct will provide what we need

Quick example of what one struct looks like: struct { int ID ; // ID for this circle float XC ; // Centre X coordinate float YC ; // Center Y coordinate float Radius ; // Radius of circle char Colour ; // Colour of circle } aCircle ; // Name of this circle data structure4Abstract Containers - structIt is up to programmers to design and define the internal fields within a struct.Keep in mind that this is a logical framework that supports being able to refer to a field within a struct struct { int ID ; // ID for this circle float XC ; // Centre X coordinate float YC ; // Center Y coordinate float Radius ; // Radius of circle char Colour ; // Colour of circle } aCircle ; // Name of this circle data container Referencing struct fields is based on hierarchical access, using the dot . operator as a binary operator connecting the name of the struct container and one of its subfields.This is demonstrated by the initialization assignments aCircle.ID = 1 ; aCircle.Radius = 1.0 ; aCircle.Colour = R ;Structure childStructure parent5Abstract Containers - structThe actual organization and allocation of memory (RAM) to each field, and to the struct as a whole, may not follow the conceptual definition.struct { int ID ; float XC ; float YC ; float Radius ; char Colour ; } aCircle ; A hole (leak) in memory6Abstract Containers - structThere is a severe limitation with respect to the examplestruct { int ID ; // ID for this circle float XC ; // Centre X coordinate float YC ; // Center Y coordinate float Radius ; // Radius of circle char Colour ; // Colour of circle } aCircle ; // Name of this circle data structure We can only define one Circle variable (or a list of variables)To overcome this, we need to define a structure type tag, hence: struct CircleStruct { // Add the type tag CircleStruct int ID ; // ID for this circle float XC ; // Centre X coordinate float YC ; // Center Y coordinate float Radius ; // Radius of circle char Colour ; // Colour of circle } ; Now the type of this structure is called struct CircleStruct7Abstract Containers - structUsing this user defined data type, one can now define multiple variables of identical (ie. compatible) data type. struct CircleStruct { int ID ; // ID for this circle float XC ; // Centre X coordinate float YC ; // Center Y coordinate float Radius ; // Radius of circle char Colour ; // Colour of circle } ; Example: struct CircleStruct aCircle1, aCircle2, AnotherCircle ;

Also very useful, create an alias name for this type (and avoid unnecessary typing) using the typedef compiler directivetypedef struct CircleStruct circleTypeName ;And then (after defining the struct itself) use: circleTypeName aCircle3, CircleArray[ 100 ], *ptrCircle ;

8Abstract Containers - structIn the following example declarations, note the implications of each data container described, based on typedef struct CircleStruct circleTypeName ;

Examples: circleTypeName aCircle3 ; // a single struct

circleTypeName CircleArray[ 100 ] ; // an array of structs

circleTypeName *ptrCircle ; // a pointer to a struct9Abstract Containers - structIt is also possible to use structs hierarchically, as shown in the example: struct objectType { circleTypeName aCircle ; rectangleTypeName aRectangle ; ellipseTypeName aEllipse ; squareTypeName aSquare ; struct objectType *ptrCircle ; } aObject ;Above, we assume that typedefs have been defined for rectangleTypeName, ellipseTypeName, and squareTypeName.One particular, important use of structs arises when we include one or more pointer fields, including cases where the pointer points to the same struct typeThis is called a self-referential data structure, to be discussed later.10Abstract Containers - structConsider the declaration of two structs, as in: struct CircleStruct aCircle1, aCircle2, arrCircle[20] ;It is vital to understand the rules and limitations concerning assignment operations and the size of the struct allocationRecall that the manner of implementation in RAM may not follow the definitionAs a consequence, holes may exist. By definition, a hole cannot be referenced, hence cannot be initialized.Any uninitialized variable may not be assigned to another variableExamples: aCircle2 = aCircle1 ; // NOT ALLOWED ! aCircle1.ID = aCircle2.ID // Copy field by field ! // Prototypevoid copyCircle( circleTypeName C1, circleTypeName C2 ) ; . . .

for( k=0; k= sizeof( int ) + 3*sizeof( float ) + sizeof( char );

Any difference between the left hand side and the right hand side is due to the size of all holes within the struct as it is implemented in RAM.Can also use the alternative syntax sizeof( struct CircleStruct )12Abstract Containers - structNow we return to deal with pointers to structsConsider the statements #typedef struct Card Card_t ; struct { int Value ; char Suit ; } Card ; Card_t Hand[52] ; Card_t * ptrCard ; . . . ptrCard = &Hand[0] ; // refer to the first card in the hand Hand[0].Value = 1 ; // deal an Ace Hand[0].Suit = S ; // make it a Spade (S, H, D, C) Hand[1] = { 3, D } ; // Deal next card as a 3 of Diamonds . . . ptrCard->Value = 10 ; // change to a 10 instead ptrCard->Suit = H ; // and make it a Heart

Note the use of the pointer-to-structure dereferencing operator, -> (a - character followed by a > character).

This operator avoids confusion using the * dereferencing operator, as shown below:

ptrCard->Value = 10 ; becomes (*ptrCard).Value = 10 ; ptrCard->Suit = H ; becomes (*ptrCard).Suit = H ;

Note how the parentheses must surround the *ptrCard reference!13Abstract Containers - structWhen a struct contains a field that is a pointer to the same struct type, it is called a self-referential data structureExample: #typedef struct Employee Empl_t ; #typedef struct EmplNode EmplNode_t ; struct Employee { int ID ; char Fname[20] ; char Lname[30] ; float Wage ; } struct EmplNode { Empl_t Empl ; EmplNode_t * ptrNext ; } EmplNode_t E1, E2 ;Based on these declarations, we show how an initialization might be achieved E1.Empl = { 2548, Roger, Dodger, 32.54 } ;E1.ptrNext = &E2 ; E2.Empl = { 2574, Marjorie, Fleischer, 32.54 } ;E2.ptrNext = NULL ;E1E2Empl dataEmpl data14Abstract Containers and LogicThe C language also provides for another abstract container called union Contains different data typesPermitting use of operations appropriate to each typeAllocates memory in a way that still supports direct access to elements? The big thing about unions is that they permit data of differing types to be located within the same memory space allocation (or overlapping, shared memory)Example: union TagName { int N ; // First declared field float F ; // Second declared field double D ; // Third declared field } aU ; aU.N = 5 ; // Must initialize using its first declared field typeThe implementation of a union is not fully standardized. Some of the allocations may overlap in RAM, but it is only guaranteed that

Sizeof( union TagName ) >= max( sizeof(int), sizeof(float), sizeof(double) )

in the example shown. Holes may be present within unions.15Abstract Containers and LogicThe union container is used primarily as a way of saving storage since many variables with different data types can re-use the same (roughly) allocated RAM storage.This is less important today than years ago due to the dramatic increases in RAM size (typically 4+GB) and lowering of costs ($/MB)Given the expanding nature and complexity of modern software (a trend that is increasing), however, it is still a good idea to be conservation minded in use of memory resources

There are many abstract problems for which the use of unions provides important opportunities for solution strategiesMost of these are based on the intricacies of data representationsQuestions:How can one acquire a set of data values of known size (# of bits or bytes) without knowing in advance what the types of the data are? How might one then determine the meaning of the data?16Logic and SequencesAs well as introducing abstract data types and containers we also consider two additional issuesBit Manipulation Enumerated data types

Boolean logicCreated by George Boole, further developed by othersFundamental operations defined on bits, or sets of bits, AND (&), OR (|), COMPLEMENT (~), and other operatorsThese allow for manipulation of bits

Enumeration of sequencesProvides for user defined data sequences (eg. days, months)Elements are assigned integer values in a (closed) rangeThese allow for conceptual simplification of related programming tasks17Logic and SequencesGeorge Boole, an English theologian, philosopher and mathematician, introduced the notions (mid 1800s) that established the foundations for Boolean Set Theory and Boolean AlgebraBoole is considered one of the founders of Computer ScienceBoolean Logic is essential for designing and constructing digital computers (von Neuman architectures)Based on notions from Set Theory

Fundamental ideas includeThe bit (binary digit) concept as a 2-valued stateBasic operations on bits, including:AND (set intersection), OR (set union), COMPLEMENT (set negation, sometimes called NOT)18Logic and SequencesBoolean concepts and operations in detailBits are represented by the values 0 or 1 only0 represents FALSE1 represents TRUEBasic operations on bits:& - AND (set intersection)

| - inclusive OR (set union)

^ - exclusive OR (set distinction)

~ - Complement (set negation)X & YY=0Y=1X=000X=101X | YY=0Y=1X=001X=111~X~XX=01X=10X ^ YY=0Y=1X=001X=11019Logic and SequencesPerforming the same operations on sets of bits are referred to as bitwise operations.Assume two ordered sets of 4 bits, A and BSpecifically: A = 1100 and B = 1010Examples:A & B: A 1100 B 1010 A&B 1000

A | B: A 1100A^B: A 1100 B 1010 B 1010 A|B 1110A^B 0110

~A: A 1100 ~A 0011Do not confuse with the relational NOT ! operator

The term bitwise operation refers to the fact that the logic operation is carried on the bits in each corresponding position, independent of other bits. 20Logic and SequencesSome interesting interpretive patterns arise for the & and | operators with certain argument values.Examples: (A0 = 00, A1 = 11, B = 10)Using & to probe or reset bit values A1 & B : A1&B = 11 & 10 = 10 = B A0 & B : A0&B = 00 & 10 = 00 All bits reset to 0Using | to probe or set bit values A1 | B : A1|B = 11 | 10 = 11 All bits set to 1 A0 | B : A0|B = 00 | 10 = 10 = BUsing ~ as a bit toggle ~ A1 : ~B = ~ 10 = 01 Toggle each bitUsing ^ to toggle bit values A1 ^ B : A1^B = 11 ^ 10 = 01 Toggle each bit A0 ^ B : A0^B = 00 ^ 10 = 10 = B No effect 21Logic and SequencesAn interesting fact about XOR.Assume two ordered sets of 4 bits, A and BRecall that A^B: A 1100 B 1010A^B 0110Now consider the sequence of statements A = A ^ B ; B = A ^ B ; A = A ^ B ;What happens to A and B? Do a trace.

A = A ^ B ; // A = 0110 B = 1010 B = A ^ B ; // A = 0110 B = 1100 A = A ^ B ; // A = 1010 B = 1100Note that A and B have been swapped !! With no temporary !!This result is fully general for bit strings of arbitrary length.

Another interesting property of ^ (xor) is illustrated in the example

B 0001 1101 0001 0111 A 0111 1010 1010 0001 A^B 0110 0111 1011 0110 A 0111 1010 1010 0001A^(A^B) 0001 1101 0001 0111

By inspection, note that the final answer has the same value as B, hence:

B == A^(A^B).

This has application in computer graphics (especially in games) where a mask, A, can be applied once to change a region, B, of pixel values (a portion of the game character), then the mask is reapplied (at a later time) to obtain the original bit values (ie. the background scene B). Such sets of bit masks for character rendering (supporting character movement within a scene as well) are often referred to as sprites.

22Logic and SequencesBoolean Logic also admits several additional operatorsNAND (NOT AND)A nand B == not ( A and B )In C: ~(A & B)NOR (NOT OR)A nor B == not ( A or B ) In C: ~(A | B)XNOR (selective OR)A xnor B == (A and B) or ((not A) and (not B)) In C: ~(A ^ B)

These are used in hardware circuit designNAND and NOR gates are considered the fundamental units of manufacture in many circuitsTransistor logic is often based on these operationsAll other operators can be expressed in terms of just one of NAND or NOR (try this out on your own!)They can also be very useful in programmingC does not provide standard library support, but these are easy to program functions for.23Logic and SequencesBefore proceeding, a quick aside on representations of integer data, using bits.The unsigned int data type has a numeric representation starting at 0 and increasing in steps of 1. In base-2, using an 8-bit container size0 00000000 1 000000011000001010 650010000110000110100 25511111111

The signed binary type int provides for both positive and negative integer numbers. Assume an arbitrary integer, N, and well call the machine representation X.X is formally defined (using logic) by:X = | N | if N>=0 , X = ~| N | + 1 if N < 0For N = 1, X = {000.0001} while for N = -1, X = {111.1111}One simple test of this logic is to verify that for every N (at least within a range of values), there correspond two signed binary representationsX = | N | and Y = - | N |where the minus sign refers to arithmetic negation (different from complementation!) and we dont need to consider N=0.For mathematical consistency, it must follow thatX + Y == 0To see that this is the case, note that :

X + Y | N | + ( ~ | N | ) + 1

{111.1111} + 1

{000.0000} + throwaway bitNote that the last step results in the required, computed value of zero. However, one must deal with the overflow bit 1 and this is handled easily by the hardware logic, literally as a throwaway bit.24Logic and SequencesAnother type of bit manipulation involves shifting of bit positions within a container.We will focus on shifting with integer types, both unsigned (logical shift) and signed binary (arithmetic shift) representationsShifting is done differently on each representationBASICS:Shift operators have two forms:Left shift: >Examples: (Assume A = 00011010) A = A > 3 ; // A = 00000011 A = A 3 ; // A = 00000011 3 A = A 3 ; // A = 11111100 4 A = A > 8 ; // A = 11111111 -1

In each example above, one must be careful in how the result is interpreted does it make sense in the context of the operation, and the application program?26Logic and SequencesAn enumerated constant is a user-defined specification of a range of values, represented symbolically, and adapted to specific programming problems.Defined by the C language statement enum eName { idlist } ;Examples: enum Workday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY }; enum Colour { Red, Green, Blue, Violet };

Each of the symbols above are assigned default values by the compiler, beginning with the first symbol (usually 0) and then incrementing by 1 the value of each successive symbol in the listThis can be modified by programmers enum Colour { Red=1, Green, Blue, Violet }; // Start at 1 enum Colour { Red=1, Green=3, Blue=4, Violet=2 }; // Redefine orderingCan check the values assigned to each symbol using a printf() statement.27Logic and SequencesEnumerated lists provide a self-documenting approach to useful symbols.Consider the following enum Colour { Red=1, Green, Blue, Violet }; // Start at 1 char ColText [ 5 ] [10 ] = { ERROR, Red, Green, Blue, Violet } ;

char * ptrColour ; ptrColour = &ColText [ Green ] ; // Using enumerated constant printf( The colour is %s\n, ptrColour ) ; // outputs the string Green

It is the ability to write code using common, intuitive terminology that makes the job easier for programmersWorking with numbers and pointers can be confusing in simple applications

28Example: Bit Fields and MasksProblem: Consider a 16-bit string that contains sub-strings, each of which carries a different interpretation as data.Such encodings are used in many applications, such as network protocol header stringsWe consider the case of graphics device control over pixel colour and intensity. For a 3-colour scheme (eg. RGB, CYM) with variable pixel intensity at 2 levels (On/Off), and each colour can be varied on a 32 level intensity scale giving a colour mix of pow(2,15) different colours (32,768 in decimal). Bit string and interpretation of fields using a unsigned short int container (16 bits).

Toggle ON/OFF field :: Values 1/0Red colour intensity field :: Value range 0..31Green colour intensity field :: Value range 0..31Blue colour intensity field :: Value range 0..31

How do we access each bit field to perform data processing?1 0 0 1 0 1 0 0 0 1 0 1 1 1 0 1Example: Bit Fields and MasksHow do we access each bit field to perform data processing?

unsigned short int Pixel ; // 16 bits with value aboveDefine bit masks unsigned int BlueMask = 31 ; // 0000000000011111 unsigned int RedMask, GreenMask, OnOffMask = 1 ; short int R, B, G ; OnOffMask