8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open world

Embed Size (px)

Citation preview

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    1/37

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    2/37

    #i f ndef GENERAL_H#def i ne GENERAL_H. . .. . .

    Following macro definitions stand for constructor types that one should consider in the process of

    implementing an abstract data type.

    #def i ne COPY 0#def i ne DEFAULT 1. . .

    Creating a copy of a Vect or object from an already existing one involves copying its components too. Witha little insight we can see that there is no universal function to serve this purpose. As a matter of fact, samedata type may require different such functions in different contexts. Same argument applies to the case of

    destroying a Vect or object.

    So, are we (the programmers) supposed to provide each and every possible copy and destruction functions?

    This beats the purpose of providing a generic container. We have to get the user to cooperate with us. And

    the way to do so is through the following pointer-to-function type definitions.

    t ypedef Obj ect ( *COPY_FUNC) ( Obj ect ) ;t ypedef voi d ( *DESTRUCTI ON_FUNC) ( Obj ect ) ;#endi f

    Vector.h

    #i f ndef VECTOR_H1.

    #def i ne VECTOR_H2.

    3.

    #i ncl ude "Gener al . h"4.

    5.

    st ruct _ VECTOR;6.

    t ypedef s t ruct _ VECTOR* Vect or ;7.

    We want to implement a generic vector. That is, a vector that can have anything as its component: a vector

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    3/37

    of i nt s, a vector of character strings, a vector of student records, and so on. Given this requirement and thefact that the structure of the component can be known only to the user [not the implementer], we need to

    ask the user for some assistance about copying and destroying components of the vector. Basically, the user

    must implement these two functions and somehow pass it to the implementer. In other words, the user and

    the implementer must cooperate; the user must fill in the missing parts in the framework that is provided by

    the implementer. A user maintaining a Vector of student records has to provide copy and destruction

    functions for student record type; a user dealing with employee records has to provide the same functions for

    employee record type; ...

    This style of programming differs from the conventional technique, where the user of the library develops

    algorithms that invoke library functions, but the overall structure of the application and flow of control

    differs for each new application. Although almost any C program makes use of the I/O library, the overall

    structure of a particular program is independent of others; routines provided in the I/O library are simply

    'low-level' operations common to all programs and do not have to be tailored to the needs of a particular

    application. This is the technique used with procedural programming languages such as Pascal and C.[2]

    In software framework usage, however, it is the overall structure, the high-level view of the algorithm that

    remains constant and is reused from application to application. The programmer (the user of the framework)

    specializes the framework, but majority of code remains the same across all applications. Because of this

    inversion in the relationship between library code and the user-supplied code, a software framework issometimes referred to as an "upside-down" library.

    The best well-known software frameworks are those associated with graphical user interfaces. The major

    tasks involved in executing a graphical program- waiting for the user to move or click the mouse, waiting for

    keystrokes, moving or resizing windows, and so on- do not change much from one application to another.

    Thus these actions can be usefully combined in a single framework not only to save programming effort in

    developing new applications, but also to ensure consistency among applications. What distinguishes one

    program from another are features such as the contents of windows and the action to be performed in

    response to a mouse click or keystroke. It is these actions that must be programmed anew in each specific

    application of the framework.

    This is the style of choice in object-oriented programming languages. To create a new application, it is

    necessary only to subclass from the original class [using inheritance] and then implement the behavior

    associated with these deferred functions. All other functionality, including the overall structure of the

    application, is obtained for free through the use of inheritance. Popular examples are the C++-based MFC

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    4/37

    (Microsoft Foundation Classes) and Java-based JFC (Java Foundation Classes).

    This style of programming (software framework) would be possible if the implementer could 'call back' to

    some user code. In an object-oriented programming language, this can be done by implementing an interface

    defined within the framework or subclassing an abstract class and implementing the abstract functionssuch

    as mouse click, keystrokes, and etc.in this class. In C, we can do this by using function pointers. All we

    have to do is to define the function signatures, which is what we are doing here, and use these definitions as

    types of parameters in certain functions. The callback takes place in these functions by the implementer

    calling the users code through the function pointer passed to the function.

    t ypedef s t ruct _Obj ect _f uncs {9.

    COPY_ FUNC copy_component ;10.

    DESTRUCTI ON_FUNC des t r oy_ component ;11.

    } Vect or _Component _Funcs;12.

    13.

    #def i ne NON_EXI STI NG_VECTOR - 114.

    15.

    #def i ne I NI T_CAP 216.

    #def i ne BOTH 317.

    The following function signature is an example to the declaration of variadic functions in C. Ellipsis used in

    the specification signifies an unknown number of parameters coming after the named arguments.[3]Number

    of arguments passed to a variadic function is deduced from the contents of one or more of the named

    arguments. Take the pri nt ffunction for instance, whose prototype is provided below.

    i nt pr i nt f ( const char *f or mat _st r i ng, . . . ) ;

    Placeholders, certain character sequences starting with %, in format_string help in figuring out the number

    and type of arguments.

    extern Vect or Vector _Cr eat e( i nt const r uct or _t ype, . . . ) ;19.

    extern i nt Vect or_Dest r oy( Vect or * t hi s) ;20.

    extern voi d Vector_ Assi gn( Vect or * l hs, const Vector r hs) ;21.

    extern Obj ect Vect or _El ement At ( const Vect or t hi s, unsi gned i nt pos) ;22.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    5/37

    extern Obj ect Vect or_I nsert At ( const Vect or t hi s, Obj ect i t em, unsi gned i nt pos) ;23.

    extern Obj ect Vect or _RemoveAt ( const Vect or t hi s, unsi gned i nt pos) ;24.

    extern Obj ect Vect or _Updat eAt ( const Vect or t hi s, Obj ect new_i t em, unsi gned i nt pos) ;25.

    extern unsi gned i nt Vector_Si ze( const Vector t hi s) ;26.

    27.

    #endi f

    28.

    Implementation

    Vector.c

    #i ncl ude 1.

    #i ncl ude 2.

    #i ncl ude 3.

    #i ncl ude

    4.

    #i ncl ude

    5.

    6.

    #i ncl ude "Gener al . h"7.

    #i nc l ude "ut i l i t y/ Vector . h"8.

    For controlling the lifetime of a particular object shared among different handles (actually pointers in our

    case), we use an extra field to hold the number of handles that provide access to the same underlying object.

    Such a field is called a reference count.

    The last field of the structure definition can be seen, for pedagogical purposes, as Obj ectcont ai ner [ ] ; . That is, a Vector is basically an array of Obj ect s. Using * instead of [ ] gives us theflexibility of changing the size of our Vect or dynamically. Had we used [ ] we would have had to specifythe size at compile time, which would have been too restrictive for our purposes.

    st ruct _VECTOR {10.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    6/37

    COPY_ FUNC copy_component ;11.

    DESTRUCTI ON_FUNC des t r oy_ component ; 12.

    unsi gned i nt r ef_ count ;13.

    unsi gned i nt cap;14.

    unsi gned i nt cap_i nc;15.

    unsi gned i nt cur_s i ze;16.

    Obj ect *contai ner ;17.

    };18.

    19.

    s t at i c BOOL adj ust_ capaci t y( const Vect or ) ; 20.

    s t at i c voi d shi f t _down( const Vect or , unsi gned i nt ) ;21.

    s t at i c voi d s hi f t _ up( const Vect or , unsi gned i nt ) ; 22.

    23.

    Vector Vect or _Creat e( i nt t ype, . . . ) {24.

    i nt i ;

    25.

    The following line declares a variable that will be used in traversing the list of unnamed arguments.

    va_ l i s t ap;26.

    Vect or exi st i ng_vec;27.

    Vect or _Component _Funcs comp_f uncs;28.

    29.

    Vect or r et_vec = ( Vect or ) mal l oc( si zeof( st ruct _ VECTOR) ) ;

    30.

    i f ( ! r et_ vec) {31.

    f pr i nt f ( st der r , " Out of memor y. . . \n" ) ;32.

    return NULL;33.

    34.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    7/37

    } /* end of (!ret_vec) */

    35.

    r et_vec- >cur _si ze = 0; 36.

    r et_vec- >ref _count = 1;37.

    r et_vec- >contai ner = NULL;

    38.

    The following macro is used to initialize the list of unnamed arguments so that an internal pointer in appoints right after the last named argument.

    va_st art ( ap, t ype) ;40.

    swi t ch ( t ype) {

    41.

    case COPY:42.

    Next line returns an argument of type Vect or and advances the internal pointer so that it points to thelocation right after this Vector argument. The run-time stack after execution of this statement is as shown

    below:[4]

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    8/37

    exi st i ng_vec = va_arg( ap, Vect or ) ;43.

    This is where we retrieve the function pointers passed by the user. Each time we need to copy or destroy a

    component we will call back to the functions found at the given addresses.

    ret _vec- >copy_ component = exi st i ng_vec- >copy_component ;44.

    r et_vec- >dest r oy_component = exi st i ng_vec- >dest r oy_c omponent ;45.

    r et_vec- >cap = ret_vec- >cur_s i ze = exi st i ng_vec- >cur _s i ze;46.

    r et_vec- >cap_i nc = exi st i ng_vec- >cap_i nc;47.

    In addition to mal l oc, we can use cal l octo allocate a region of memory from the heap. This functionallocates memory large enough to hold n (passed as the first argument) elements, each of size m (passed as

    the second element); it returns a pointer to the first element of the array. This can certainly be done by

    mal l oc. As an extra, the returned region is bitwise zeroed, which is not done by mal l oc.

    Memory allocated cal l occan be returned using f reeor cf r ee. But keep in mind that despite its

    omnipresence cf reeis not a standard C function.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    9/37

    Question:

    Can we use cal l octo allocate memory that holds an i nt with an initial value of 0? What about af l oat with an initial value of 0.0? Can you guarantee that answer will always be the same?

    f l oat *f = ( f l oat *) cal l oc( 1, si zeof( f l oat ) ) ; /* What is the value contained in *f? Is it 0.0? */ i nt *i = ( i nt *) cal l oc( 1, si zeof( i nt ) ) ;

    /* What is the value contained in *i? Is it 0? */

    Answer

    Given the ubiquity of number representation standards the answer to the first part of question is very

    likely to be affirmative. However, we still cannot give any guarantees.

    ret _vec- >cont ai ner = c al l oc( exi st i ng_vec- >cur_s i ze, s i zeof( Obj ect ) ) ;48.

    f or ( i = 0; i cur_s i ze; i ++) 49.

    r et_vec- >cont ai ner [ i ] = exi st i ng_vec- >copy_component ( exi st i ng_vec- >cont ai ner [ i ] ) ;50.

    break;51.

    case DEFAULT:

    52.

    comp_f uncs = va_arg( ap, Vect or _Component _Funcs) ;53.

    r et_vec- >copy_ component = comp_f uncs. copy_component ;54.

    r et_vec- >dest r oy_component = comp_f uncs . dest r oy_component ;55.

    r et_vec- >cap = ret_vec- >cap_i nc = 0;56.

    break;

    57.

    case I NI T_CAP:58.

    comp_f uncs = va_arg( ap, Vect or _Component _Funcs) ;59.

    r et_vec- >copy_ component = comp_f uncs. copy_component ;60.

    r et_vec- >dest r oy_component = comp_f uncs . dest r oy_component ;61.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    10/37

    ret _vec- >cap = va_arg( ap, unsi gned i nt ) ;62.

    r et_vec- >cap_i nc = 0;63.

    i f ( r et _vec- >cap cont ai ner = c al l oc( r et _vec- >cap, s i zeof( Obj ect ) ) ;65.

    break;

    66.

    case BOTH: 67.

    comp_f uncs = va_arg( ap, Vect or _Component _Funcs) ;68.

    r et_vec- >copy_ component = comp_f uncs. copy_component ;69.

    r et_vec- >dest r oy_component = comp_f uncs . dest r oy_component ;70.

    r et_vec- >cap = va_arg( ap, unsi gned i nt ) ;

    71.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    11/37

    ret _vec- >cap_i nc = va_arg( ap, unsi gned i nt ) ;72.

    i f ( r et _vec- >cap cont ai ner = c al l oc( r et _vec- >cap, s i zeof( Obj ect ) ) ;74.

    break;75.

    } /* end of switch(type) */

    76.

    va_endperforms necessary cleanup operations on ap. In other words, it serves the purpose of a destructor.It should be called by the programmer after all arguments have been read with va_ar g.

    va_end( ap) ;77.

    78.

    return( r et_ vec) ;79.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    12/37

    Question:

    Which one of the following memory layouts is more reasonable for implementing variadic functions?

    Answer

    We know that named arguments and local variables are at fixed LB-relative addresses. Depending on

    whether the run-time stack grows downward or upward, if arguments are at (LB offset) then local

    variables are at (LB + offset); if arguments are at (LB + offset) then local variables are at (LB offset). Such an arrangement enables the compiler to fix LB-relative addresses of these items at

    compile-time. Now that memory reserved for unnamed arguments can vary depending on the number

    and size of such items, the above scheme becomes impossible to guarantee with the choice on the right

    side. So, the correct answer is right-to-left.

    Insert figure

    The names are due to the order of push operations. In right-to-left, first argument to be pushed on the

    run-time stack is the rightmost argument in the argument list, while in left-to-right it is the leftmost that

    is pushed first.

    [5]

    For this reason, a programming language supporting variadic functions, such as C, will naturally use

    right-to-left, while a language like Pascal, which doesnt support variadic functions, can choose either

    arrangement. In a call to non-variadic function a C compiler may be (by means of a environment

    specific directive) directed to pass the arguments in the opposite direction.[6]

    Question:

    In C, which one do you think is responsible for removing the arguments from the run-time stack, caller or

    the callee?

    Answer

    Compiled code corresponding to the callee, just like any other code, is immutable. This means the code

    template used for removing the arguments is fixed. However, the number of bytes pushed on the

    runtime stack varies with the number of arguments and their types and this bit of information will

    probably change for each invocation. This means the compiler cannot foresee the number of bytes

    passed to the callee and synthesize a template for argument removal. For this reason, this template is

    synthesized differently for each invocation and appended right after the point of call. So, it is the

    callers responsibility to remove the arguments from the runtime stack.[7]

    } /* end of Vector Vector_Create(Constructor_type, struct basic_funcs, ...) */80.

    The structure of a Vect or object is as given below.

    Insert figure

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    13/37

    The user accesses a Vect or object through a handle (this variable in the figure). The representation ishidden and it is modified only through the functions in the public interface of Vect or .

    Note that the handle is a pointer to the properties of the Vect or , not to its components. This is the typicalapproach taken to implement collection types. You have a handle on some metadata, which (in addition to

    defining properties of the collection) has a handle on the container that is used to hold the components.

    i nt Vector _Dest r oy( Vect or * t hi s) {82.

    i nt i ;83.

    Vect or t hi s_copy = *t hi s;84.

    85.

    i f ( t hi s_copy == NULL) return( NON_EXI STI NG_VECTOR) ;

    86.

    The Vect or _Dest r oyfunction having been called doesnt mean the underlying object will be destroyed.In the case of an object that is shared among different handles, the reference count is decremented and the

    underlying object is left untouched. If the reference count is one we are about to severe the tie between the

    object and the last handle on it. In such a situation, we must also destroy the underlying object!

    i f( t hi s_copy- >r ef _count > 1) {87.

    *t hi s = NULL;88.

    return( - - t hi s_copy- >r ef _count ) ;89.

    } /* end of if(this_copy->ref_count > 1) */90.

    Note that dest r oy_component is a pointer to function. That is, the function is called through a pointer;we can change the function being invoked by assigning different pointer values. This is actually what gives

    us the ability to deal with different types of data.[8]

    f or ( i = t hi s_copy- >cur _si ze - 1; i >= 0; i - - )

    92.

    t hi s_copy- >dest r oy_component ( t hi s_copy- >cont ai ner [ i ] ) ) ;93.

    94.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    14/37

    f r e e( t hi s_copy- >cont ai ner ) ; f r e e( t hi s_copy) ;95.

    * t hi s = NULL;96.

    97.

    return 0;98.

    } /* end of int Vector_Destroy(Vector*) */99.

    100.

    Obj ect Vect or_ El ement At ( const Vector t hi s , unsi gned i nt pos ) {101.

    Obj ect r et_obj ect ;102.

    103.

    i f ( pos >= t hi s- >cur_ s i ze) return NULL;104.

    See that we return a copy of the required component, not a pointer to it. The rationale behind this is to avoid

    giving any access to the underlying data structure.

    r et _obj ect = t hi s- >copy_component ( t hi s - >cont ai ner [ pos] ) ;105.

    106.

    return( r et_ obj ect ) ;107.

    } /* end of Object Vector_ElementAt(const Vector, unsigned int) */108.

    Next function assigns a Vect or object to another. Since we dont have operator overloading in C, we haveto come up with a function name and use this name to perform assignment. Of course, we could still use '='

    to do this. But, doing so would lead to an inconsistent state, where reference count and the number of

    handles sharing the underlying object do not agree.

    Vect or v1, v2;v1 = Vect or _Cr eat e( DEFAULT, . . . ) ;Vect or _I nser t At ( v1, . . . ) ; . . . ; . . . ; Vector _I nser t At ( v1, . . . ) ; . . .

    . . .Vect or _Assi gn( &v2, v1) ;. . .

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    15/37

    The previous code fragment will produce the picture given below.

    Insert figure

    voi d Vect or_Assi gn( Vect or * l hs, const Vector r hs{110.

    Vector _Dest r oy( l hs) ;111.

    * l hs = r hs;112.

    r hs- >r ef _count++;113.

    } /* end of void Vector_Assign(Vector*, const Vector) */

    114.

    115.

    Obj ect Vect or _I nser t At ( const Vect or t hi s , Obj ect new_i t em, unsi gned i nt pos ) {

    116.

    i f ( t hi s - >cur_s i ze cur_ s i ze;117.

    Before we make the insertion, we have to make sure there is enough room in our structure. If not, we adjust

    the container capacity according to some predefined formula. In case we may be out of heap memory, we do

    not effect any changes in the structure and just return a NULLvalue from the function. Otherwise, we extendthe memory region needed for the container and go ahead with the insertion: if the new component is

    inserted at the end just copy it at the end of the vector, which is indicated by the cur _si zefield; if the newcomponent is inserted somewhere other than the end, shift the components that are to come after location of

    the new item down by one and make the insertion.

    i f ( t hi s - >cap == t hi s - >cur _s i ze)118.

    i f ( ! adj ust_ capaci t y( t hi s) ) return NULL;119.

    i f ( pos ! = t hi s- >cur_ s i ze) shi f t _down( t hi s , pos) ;120.

    t hi s- >cont ai ner [ pos] = t hi s- >copy_component ( new_i t em) ;121.

    t hi s- >cur _s i ze++;122.

    123.

    return new_i t em;124.

    } /* end of Object Vector_InsertAt(const Vector, Object, unsigned int) */125.

    126.

    127.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    16/37

    Obj ect Vect or _RemoveAt ( const Vect or t hi s , unsi gned i nt pos ) {

    Obj ect r et_obj ect ;128.

    129.

    i f ( pos >= t hi s- >cur_ s i ze) return NULL;130.

    ret_obj ect = *( t hi s- >cont ai ner + pos) ;

    131.

    i f ( pos ! = t hi s- >cur_ s i ze - 1) shi f t _up( t hi s, pos) ;132.

    t hi s- >cur _s i ze- - ;133.

    134.

    return( r et_ obj ect ) ;135.

    } /* end of Object Vector_RemoveAt(const Vector, unsigned int) */136.

    137.

    Obj ect Vect or_ UpdateAt ( const Vect or t hi s , Obj ect new_i t em, unsi gned i nt pos ) {138.

    Obj ect ol d_val ue;139.

    140.

    i f ( pos >= t hi s- >cur_ s i ze) return NULL;141.

    142.

    ol d_val ue = *( t hi s- >cont ai ner + pos) ;143.

    t hi s- >cont ai ner [ pos] = t hi s- >copy_component ( new_val ue) ;144.

    145.

    return ol d_val ue;146.

    } /* end of Object Vector_UpdateAt(const Vector, Object, unsigned int)*/

    147.

    148.

    unsi gned i nt Vector_Si ze( const Vector t hi s) { return( t hi s - >cur_s i ze) ; }149.

    adj ust _capaci t yfunction extends the capacity of a Vector according to some given formula. In ourimplementation, we adopt the formula used in most C++ compilers: if the Vect or has a nonzero capacity

    increment value, capacity is incremented by this amount; if the user has not provided any value for this fieldor it is zero, the new capacity is calculated by doubling the previous one. (If the current capacity value is

    zero then new capacity is taken to be one.) Failure to allocate enough room for the Vect or object results inreturning a FALSEvalue.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    17/37

    s t at i c BOOL adj ust_ capaci t y( const Vector thi s) {151.

    i nt i ;152.

    const Vector o l d_t hi s = ( Vect or ) mal l oc( si zeof( st ruct _ VECTOR) ) ;

    153.

    i f( ! ol d_ thi s) {154.

    f pr i nt f ( st der r , " Out of memor y. . . \n" ) ;

    155.

    return FALSE;156.

    } /* end of if(!old_this) */157.

    memcpy( ol d_ th i s, t hi s , s i zeof( st ruct _ VECTOR) ) ;158.

    159.

    i f ( t hi s - >cap_i nc ! = 0) t hi s- >cap += t hi s- >cap_i nc;160.

    el s e i f ( t hi s- >cap == 0) t hi s - >cap = 1;161.

    el se t hi s- >cap *= 2;162.

    t hi s- >cont ai ner = c al l oc( t hi s - >cap, s i zeof( Obj ect ) ) ;163.

    164.

    i f ( ! t hi s- >cont ai ner ) {165.

    t hi s- >cap = ol d_ th i s- >cap;166.

    t hi s- >cont ai ner = ol d_ th i s- >cont ai ner ;167.

    f r e e( ol d_ th i s) ;168.

    f pr i nt f ( st der r , " Out of memor y. . . \n" ) ;

    169.

    return FALSE;

    170.

    } /* end of if(!this->container) */171.

    172.

    i f ( ol d_ thi s - >cap == 0) {173.

    f r e e( ol d_ th i s) ;174.

    return TRUE;

    175.

    } /* end of if(old_this->cap == 0) */176.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    18/37

    memcpy( t hi s- >cont ai ner , ol d_ thi s- >cont ai ner , 177.

    si zeof( Obj ect ) * ol d_ thi s - >cur_s i ze) ;178.

    179.

    f r e e( ol d_ thi s - >cont ai ner ) ;

    180.

    f r e e( ol d_ thi s) ;181.

    return TRUE;182.

    } /* end of BOOL adjust_capacity(const Vector) */183.

    Shifting down is required whenever a new item is inserted into any location other than the end of the

    Vect or .

    s t at i c voi d shi f t _down( const Vect or t hi s , unsi gned i nt pos ) {185.

    unsi gned i nt i ;186.

    f or ( i = t hi s - >cur _s i ze; i > pos ; i - - )187.

    memcpy( t hi s- >cont ai ner + i , t hi s- >cont ai ner + ( i - 1) , s i zeof( Obj ect ) ) ;188.

    } /* end of void shift_down(const Vector, unsigned int) */189.

    Similarly, shifting up is required whenever an item is removed from any location other than the end of the

    Vect or .

    s t at i c voi d s hi f t _ up( const Vector t hi s, unsi gned i nt pos) {191.

    unsi gned i nt i ;192.

    f or ( i = pos; i cur_s i ze - 1; i ++)193.

    memcpy( t hi s- >cont ai ner + i , t hi s- >cont ai ner + ( i + 1) , s i zeof( Obj ect ) ) ;194.

    } /* end of void shift_up(const Vector, unsigned int) */195.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    19/37

    Test Programs

    Vector_Test.c

    #i ncl ude 1.

    2.

    #i ncl ude "Gener al . h"3.

    #i ncl ude "Wr apper s. h"4.

    #i nc l ude "ut i l i t y/ Vector . h"5.

    6.

    enum {CREATE_COPY = 1, CREATE_DEFAULT, DESTROY, I NSERT = 6, PEEK, REMOVE, UPDATE, DI SPLAY, EXI T7.

    8.

    Vector v[ 2] ;9.

    10.

    voi d di spl ay_vec( unsi gned i nt whi ch) {11.

    unsi gned i nt i ;

    12.

    13.

    i f ( ! v[ whi ch] ) {14.

    pr i nt f ( " - - - - - \n" ) ;

    15.

    return; 16.

    } /* end of if(!v[which]) */17.

    pr i nt f ( " +++++\n" ) ;18.

    pr i nt f ( " Cont ent s of vect or #%d\n" , whi ch) ;19.

    f or ( i = 0; i

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    20/37

    } /* end of void display_vec(unsigned int) */

    26.

    i nt mai n( voi d) {27.

    i nt val ;28.

    I nteger pval ;

    29.

    unsi gned i nt act i on, pos, whi ch_vec, f r om_whi ch_vec;30.

    Vect or _Component_ Funcs i nt _f uncs = {&I nteger_ CopyI nteger , &I nt eger_Destr oyI nt eger};31.

    32.

    do {33.

    scanf( " %d" , &act i on) ;34.

    swi t ch ( ac t i on) {35.

    case CREATE_COPY:36.

    scanf( " %d %d" , &whi ch_vec, &f r om_whi ch_vec) ;37.

    pr i nt f ( "Tr yi ng t o cr eat e a copy of vect or #%d i nto vector #%d. . . " , f r om_whi ch_vec, w i c _ 38.

    v[ whi ch_vec] = Vect or_Creat e( COPY, v[ f r om_whi ch_vec] ) ;39.

    i f ( v[ whi ch_vec] ) pr i nt f ( " +++++\n" ) ;40.

    el se pr i nt f ( " - - - - - \n" ) ;41.

    break;42.

    case CREATE_DEFAULT:43.

    scanf( " %d" , &whi ch_vec) ;44.

    pr i nt f ( "Tryi ng t o cr eat e vect or #%d usi ng def aul t const r uct or. . . " , whi ch_vec) ;

    45.

    v[ whi ch_vec] = Vect or_Creat e( DEFAULT, i nt _ f uncs ) ;46.

    i f ( v[ whi ch_vec] ) pr i nt f ( " +++++\n" ) ;47.

    el se pr i nt f ( " - - - - - \n" ) ;48.

    break;49.

    case DESTROY:

    50.

    scanf( " %d" , &whi ch_vec) ;51.

    pr i nt f ( "Tryi ng to dest r oy vect or#%d. . . " , whi ch_vec) ;52.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    21/37

    i f ( ! Vector _Dest r oy( &v[ whi ch_vec] ) ) pr i nt f ( " +++++\n" ) ;53.

    el se pr i nt f ( " - - - - - \n" ) ;54.

    break;

    55.

    case I NSERT:56.

    scanf( " %d %d %d" , &whi ch_vec, &pos, &val ) ;57.

    pr i nt f ( "Tryi ng to i nser t %d at posi t i on %d of vect or#%d. . . " , val , pos, whi ch_vec) ;58.

    Note we insert Integer objectswhich are basically objects of an opaque type that wrap around an intnot

    ints. This is a consequence of the genericness provided by means of void*, which requires insertion of

    pointers.

    pval = I nt eger_Cr eat e( val ) ;59.

    i f ( Vector_ I nsert At ( v[ whi ch_vec] , pval , pos) ) pr i nt f ( " +++++\n" ) ;60.

    el se pr i nt f ( " - - - - - \n" ) ;61.

    break;

    62.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    22/37

    case REMOVE:63.

    scanf( " %d %d" , &whi ch_vec, &pos) ;64.

    pr i nt f ( "Tryi ng to r emove t he i t emat posi t i on %d f r om vect or#%d. . . " , pos, whi ch_vec) ;65.

    Now that the value returned (ret_obj) will be assigned to pval, we will have a handle on the removed object

    through pval.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    23/37

    pval = Vect or _RemoveAt ( v[ whi ch_vec] , pos) ;66.

    i f ( pval ) pr i nt f ( " +++++%d\n" , I nteger_Val ue( pval ) ) ;67.

    el se pr i nt f ( " - - - - - \n" ) ;68.

    break; 69.

    case PEEK:

    70.

    scanf( " %d %d" , &whi ch_vec, &pos) ;71.

    pr i nt f ( "Tr yi ng t o peek i n vect or#%d at posi t i on %d. . . " , whi ch_vec, pos) ;72.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    24/37

    Realize the object is cloned and then returned. This new object, after assignment to pval, can be manipulated

    independently of the original copy.

    pval = Vect or _El ement At ( v[ whi ch_vec] , pos) ;73.

    i f ( pval ) pr i nt f ( " +++++%d\n" , I nteger_Val ue( pval ) ) ;74.

    el se pr i nt f ( " - - - - - \n" ) ;75.

    break;76.

    case UPDATE:

    77.

    scanf( " %d %d %d" , &whi ch_vec, &pos, &val ) ;78.

    pr i nt f ( "Tr yi ng t o updat e posi t i on %d of vect or#%d wi t h %d. . . " , pos, whi ch_vec, val ) ;79.

    pval = I nt eger_Cr eat e( val ) ;80.

    i f ( Vect or _UpdateAt ( v[ whi ch_vec] , pval , pos) )81.

    pr i nt f ( "+++++\n" ) ;

    82.

    el se pr i nt f ( " - - - - - \n" ) ;83.

    break;84.

    case DI SPLAY:85.

    scanf( " %d" , &whi ch_vec) ;86.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    25/37

    pr i nt f ( "Tryi ng t o di spl ay vect or#%d. . . " , whi ch_vec) ;87.

    di spl ay_vec( whi ch_vec) ;88.

    break;89.

    case EXI T:90.

    ex i t ( 0) ;91.

    } /* end of switch(action) */92.

    } whi l e ( 1) ;93.

    } /* end of int main(void) */94.

    Running the Test Program

    (Using Cygwin)

    gcc c ID:/include Vector.c

    gcc o Vector_Test.exe Vector_Test.c Vector.o lWrappers ID:/include LD:/library

    The above command will bring into the executable the required object files found in the [static] library

    named libWrappers.a. Name of the library to use is figured out by simply prefixing "lib" and suffixing ".a" to

    the file name supplied with the l switch. Search for this library will make use of the directory passed with

    the L switch.

    Vector_Test < Vector_Test.input > Vector_Test.output

    This command will redirect both input and output to disk files. It will still make the program believe that it is

    receiving its input from the keyboard and sending its output to the screen. This becomes possible by

    remapping stdin and stdout to different physical files. With no remapping, all processes in a system have the

    following initial file table:

    Per-process open file tablePhysical file Other fields

    0 Keyboard ...

    1 Screen ...

    2 Screen ...

    After remapping we have:

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    26/37

    Per-process open file table afterredirection

    Physical file Other fields

    0 Vector_Test.input ...

    1 Vector_Test.output ...

    2 Screen ...

    For both before and after remapping, we have the following macro definitions in place:

    #def i ne st di n 0#def i ne st dout 1#def i ne st der r 2

    This is all done by the command-line interpreter. The user doesnt need to make any modifications in the

    source code; (s)he can still program as if input were entered at the keyboard and output were written to the

    screen. This is possible because we read from or write to a physical file through a handle (logical file). If wechange the physical file the handle is mapped to, although we write to the same logical file (handle) the final

    destination affected changes.

    Vector_Test.input

    2 06 0 10 56 0 10 156 0 8 206 0 8 256 0 2 306 0 0 3510 08 0 28 0 38 0 10010 01 1 08 1 1

    7 1 09 1 2 2610 17 0 27 0 510 03 010 00

    Vector_Test.output

    Tryi ng t o cr eate vect or #0 usi ng def aul t const r uct or. . . +++++

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    27/37

    Tryi ng t o i nser t 5 at posi t i on 10 of vect or #0. . . +++++Tryi ng t o i nser t 15 at posi t i on 10 of vect or #0. . . +++++Tryi ng t o i nser t 20 at posi t i on 8 of vect or #0. . . +++++Tryi ng t o i nser t 25 at posi t i on 8 of vect or #0. . . +++++Tryi ng t o i nser t 30 at posi t i on 2 of vect or #0. . . +++++Tryi ng t o i nser t 35 at posi t i on 0 of vect or #0. . . +++++Tryi ng t o di spl ay vect or#0. . . +++++

    Cont ent s of vect or #0#0: 35 #1: 5 #2: 15 #3: 30 #4: 20 #5: 25

    Tryi ng t o r emove t he i t em at posi t i on 2 f r om vect or #0. . . +++++15Tryi ng t o r emove t he i t em at posi t i on 3 f r om vect or #0. . . +++++20Tryi ng t o r emove t he i t em at posi t i on 100 f r om vector#0. . . - - - - -Tryi ng t o di spl ay vect or#0. . . +++++Cont ent s of vect or #0#0: 35 #1: 5 #2: 30 #3: 25

    Tryi ng t o cr eate a copy of vect or#0 i nto vect or#1. . . +++++Tryi ng t o r emove t he i t em at posi t i on 1 f r om vect or #1. . . +++++5

    Tryi ng t o peek i n vect or#1 at posi t i on 0. . . +++++35Tryi ng t o update posi t i on 2 of vect or #1 wi t h 26. . . +++++Tryi ng t o di spl ay vect or#1. . . +++++Cont ent s of vect or #1#0: 35 #1: 30 #2: 25

    Tryi ng t o peek i n vect or#0 at posi t i on 2. . . +++++30Tryi ng t o peek i n vect or#0 at posi t i on 5. . . - - - - -Tryi ng t o di spl ay vect or#0. . . +++++Cont ent s of vect or #0#0: 35 #1: 5 #2: 30 #3: 25

    Tryi ng t o dest r oy vect or#0. . . +++++

    Tryi ng t o di spl ay vect or#0. . . - - - - -

    Object Module Libraries

    Whether you use them or not, linking statically with an object module brings in all the functionality within

    the module. This means code you never use in your program will be there to increase size of the executable.

    One can avoid this by splitting the contents of the module into smaller chunks. Using these smaller modules

    will probably reduce the size of the executable but you now face another problem: having to write the names

    of the object modules separately on the command line.[9]

    Libraries offer a combination of both worlds.[10]Linking with a library means all external entities within the

    individual modules are visible. However, only the modules that are used are brought into the executable.

    Switching from one module to another in the library does not force you to change the command line.

    Everything is taken care of by the linker and the library manager.

    Example: Suppose libWrappers.a contains Integer.o, Char.o, Short.o, and so on. Having used some

    functionality from Integer.o, the following command will cause only Integer.o to be brought in.

    gcc o Vector_Test.exe Vector_Test.c Vector.o lWrappers ID:/include LD:/library

    If we later decide to use some function from, say, Char.o, we dont need to make any modifications on the

    command line. The linker-library manager pair will sort out the details for us and bring in only Char.o and

    Integer.o.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    28/37

    Definition: A libraryis an archive of object modules, whichin addition to the modulesgenerally has

    some sort of metadata to quicken locating the individual files.

    Library Header File

    Wrappers.h includes forward declarations and prototypes required for boxing primitive type data and

    unboxing wrapped data. Note same thing could have been done by placing relevant information in separate

    header files. There is no rule saying that one must have a single header file for an entire library. As a matterof fact, you can have a separate header file for each and every object module [or even function] in the

    library. Choosing to have a separate header file for each object module, however, has a disadvantage: As you

    add a new function call in your code you have to figure out the header file it comes from and [probably] add

    a relevant include directive, which is a reincarnation of the problem of having to write multiple object files

    on the command line.

    In some cases, striking a balance between the two extremes might be a better choice. Take, for instance, a

    math library that offers tens, if not hundreds, of functions. Sifting through a single header file in such a case

    is admittedly a painstaking process. Having multiple headers corresponding to different aspects of the math

    library might be a good idea.

    Wrappers.h

    #i f ndef WRAPPERS_H1.

    #def i ne WRAPPERS_H2.

    3.

    #i ncl ude "Gener al . h"4.

    Since our generic vector expects an opaque pointer as its component, using it with primitive data may turn

    out to be painful: You must first wrap the data and use the pointer to this wrapped data in your transactions.

    Later on when you want to print the data to some medium, you must do some unboxingthat is, retrieve the

    contents of the region pointed by the opaque pointerand then print the data. Similar things can be said

    about comparing, copying, and destroying the data.

    This pattern is so common that a special library (libWrappers.a) is offered for the users convenience. In case

    (s)he may want to use the Vector module and the like with primitive data types, (s)he doesnt have to

    reinvent the wheel; all (s)he has to do is to use the functions found in libWrappers.a.

    The whole thing can be likened to the wrapper classes in Java and the concept of automatic boxing-unboxing

    in C#. As a matter of fact, this way of using a container is so frequent that Java, as of 1.5, supports automatic

    boxing-unboxing.

    st ruct _CHAR;6.

    t ypedef s t ruct _CHAR* Char ;7.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    29/37

    extern Char Char _Cr eat e( unsi gned char val ) ;8.

    extern voi d Char _Dest r oy( Char * t hi s) ;9.

    10.

    extern i nt Char _Compar eChar s( Obj ect , Obj ect ) ;11.

    extern Obj ect Char _CopyChar ( Obj ect ) ;12.

    extern voi d Char _Dest r oyChar ( Obj ect ) ;13.

    14.

    extern unsi gned char Char _Val ue( Char wr appedChar ) ;

    15.

    16.

    st ruct _ SCHAR;17.

    t ypedef s t ruct _ SCHAR* SChar ;18.

    extern SChar SChar_ Cr eate( si gned char val ) ;19.

    extern voi d SChar _Dest r oy( SChar * t hi s) ;

    20.

    21.

    extern i nt SChar _Compar eSChar s( Obj ect , Obj ect ) ;22.

    extern Obj ect SChar _CopySChar ( Obj ect ) ;23.

    extern voi d SChar_ Dest r oySChar( Obj ect ) ;24.

    25.

    extern si gned char SChar _Val ue( SChar wr appedSChar ) ;26.

    27.

    st ruct _ I NTEGER;28.

    t ypedef s t ruct _ I NTEGER* I nteger ;29.

    extern I nt eger I nt eger_Cr eat e( si gned i nt val ) ;30.

    extern voi d I nteger _Destr oy( I nt eger* t hi s) ;31.

    32.

    extern i nt I nt eger_ Compar eI nt eger s( Obj ect , Obj ect ) ;33.

    extern Obj ect I nteger_ CopyI nteger ( Obj ect ) ;34.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    30/37

    extern voi d I nteger _Destr oyI nt eger ( Obj ect ) ;

    35.

    36.

    extern si gned i nt I nt eger _Val ue( I nt eger wr appedI nt ) ;37.

    38.

    st ruct _UI NTEGER;39.

    t ypedef s t ruct _ UI NTEGER* UI nteger ;

    40.

    extern UI nteger UI nteger _Cr eat e( unsi gned i nt val ) ;41.

    extern voi d UI nteger_ Dest r oy( UI nt eger * t hi s) ;42.

    43.

    extern i nt UI nt eger _Compar eUI nteger s( Obj ect , Obj ect ) ;44.

    extern Obj ect UI nteger_ CopyUI nt eger ( Obj ect ) ;

    45.

    extern voi d UI nteger_ Dest r oyUI nteger ( Obj ect ) ;46.

    47.

    extern unsi gned i nt UI nteger_ Val ue( UI nt eger wr appedUI nt ) ;48.

    49.

    st ruct _LONG;

    50.

    t ypedef s t ruct _LONG* Long;51.

    extern Long Long_Cr eat e( si gned l ong val ) ;52.

    extern voi d Long_Dest r oy( Long* t hi s) ;53.

    54.

    extern i nt Long_ Compar eLongs ( Obj ect , Obj ect ) ;55.

    extern Obj ect Long_CopyLong( Obj ect ) ;56.

    extern voi d Long_Dest r oyLong( Obj ect ) ;57.

    58.

    extern si gned l ong Long_Val ue( Long wr appedLong) ;59.

    60.

    st ruct _ULONG;61.

    62.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    31/37

    t ypedef s t ruct _ULONG* ULong;

    extern ULong ULong_Cr eat e( unsi gned l ong val ) ;63.

    extern voi d ULong_Dest r oy( ULong*) ;64.

    65.

    extern i nt ULong_ Compar eULongs( Obj ect , Obj ect ) ;66.

    extern Obj ect ULong_CopyULong( Obj ect ) ;67.

    extern voi d ULong_Dest r oyULong( Obj ect ) ;68.

    69.

    extern unsi gned l ong ULong_Val ue( ULong wr appedULong) ;

    70.

    71.

    st ruct _SHORT;72.

    t ypedef s t ruct _SHORT* Shor t ;73.

    extern Shor t Shor t _Create( si gned shor t val ) ;74.

    extern voi d Shor t _Dest r oy( Shor t * ) ;

    75.

    76.

    extern i nt Shor t _CompareShor t s( Obj ect , Obj ect ) ;77.

    extern Obj ect Short _CopyShor t ( Obj ect ) ;78.

    extern voi d Shor t _Dest r oyShort ( Obj ect ) ;79.

    80.

    extern si gned short Shor t _Val ue( Shor t wr appedShor t ) ;81.

    82.

    st ruct _USHORT;83.

    t ypedef s t ruct _USHORT* UShor t ;84.

    extern UShort UShort _Creat e( unsi gned shor t val ) ;85.

    extern voi d UShor t _Dest r oy( UShor t * ) ;86.

    87.

    extern i nt UShor t _CompareUShort s( Obj ect , Obj ect ) ;88.

    extern Obj ect UShor t _CopyUShor t ( Obj ect ) ;89.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    32/37

    extern voi d UShor t _Dest r oyUShor t ( Obj ect ) ;90.

    91.

    extern unsi gned shor t UShor t _Val ue( UShor t wr appedUShort ) ;92.

    93.

    st ruct _ DOUBLE;94.

    t ypedef s t ruct _ DOUBLE* Doubl e;

    95.

    extern Doubl e Doubl e_Create( doubl e val ) ;96.

    extern voi d Doubl e_Dest r oy( Doubl e*) ;97.

    98.

    extern voi d Doubl e_Dest r oyDoubl e( Obj ect ) ;99.

    extern i nt Doubl e_Compar eDoubl es( Obj ect , Obj ect ) ;

    100.

    extern Obj ect Doubl e_CopyDoubl e( Obj ect ) ;101.

    102.

    extern doubl e Doubl e_Val ue( Doubl e wr appedDoubl e) ;103.

    104.

    st ruct _FLOAT;

    105.

    t ypedef s t ruct _FLOAT* Fl oat ;106.

    extern F l oat F l oat_ Cr eat e( f l oat val ) ;107.

    extern voi d Fl oat _Destr oy( Fl oat *) ;108.

    109.

    extern voi d Fl oat _Destr oyFl oat ( Obj ect ) ;

    110.

    extern i nt Fl oat_ Compar eFl oat s( Obj ect , Obj ect ) ;111.

    extern Obj ect Fl oat _CopyFl oat ( Obj ect ) ;112.

    113.

    extern f l oat F l oat _Val ue( Fl oat wr appedFl oat ) ;114.

    115.

    #endi f116.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    33/37

    A Sample Module

    What follows is an implementation of the wrapper interface for type int. Wrappers for the other primitive

    types can be provided similarly and will not be included in this handout.

    Integer.c

    #i ncl ude 1.

    #i ncl ude 2.

    #i ncl ude 3.

    4.

    #i ncl ude "Wr apper s. h"

    5.

    6.

    st ruct _ I NTEGER { si gned i nt val ue; };7.

    8.

    I nt eger I nt eger _Creat e( si gned i nt val ) {9.

    I nt eger t hi s = ( I nt eger ) mal l oc( si zeof( st ruct _ I NTEGER) ) ;

    10.

    i f ( ! t hi s) {11.

    f pr i nt f ( st der r , " Out of memor y. . . \n" ) ;12.

    return NULL;13.

    } /* end of if(!this) */14.

    t hi s- >val ue = val ;15.

    16.

    return t hi s;17.

    } /* Integer Integer_Create(signed int) */18.

    19.

    voi d I nt eger_Destr oy( I nteger * t hi s) {

    20.

    I nt eger t hi s_copy = * t hi s ;21.

    i f ( t hi s_copy == NULL) return;22.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    34/37

    23.

    f r e e( t hi s_copy) ;24.

    * t hi s = NULL;25.

    } /* end of void Integer_Destroy(Integer*) */26.

    27.

    voi d I nt eger_Destr oyI nt eger ( Obj ect t hi s) {28.

    I nt eger_Dest r oy( ( I nt eger* ) &t hi s) ;29.

    } /* void Integer_DestroyInteger(Object) */30.

    31.

    i nt I nteger_ Compar eI nt eger s( Obj ect t hi s, Obj ect r hs) {32.

    si gned i nt t hi sVal ue = ( ( I nt eger ) t hi s) - >val ue;33.

    si gned i nt r hsVal ue = ( ( I nt eger ) r hs) - >val ue;34.

    35.

    i f ( t hi sVal ue == rhsVal ue) return 0;36.

    el s e i f ( thi sVal ue val ue) ;42.

    43.

    return r etVal ;44.

    } /* Object Integer_CopyInteger(Object) */

    45.

    46.

    si gned i nt I nt eger_Val ue( I nt eger wr appedI nt ) {47.

    return wr appedI nt - >val ue;48.

    } /* signed int Integer_Value(Integer) */49.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    35/37

    Building the Library

    Using Cygwin

    Before building the library we need to create the individual object modules that are to go into it.

    gcc c Char . c I D: /i ncl udegcc c I nt eger . c I D: /i ncl ude...

    ...

    If all source files are in the same directory and no other files exist in that location, you can do it all in one

    step:

    gcc c *. c I D: /i ncl ude

    We can now create the libraryor archive in Unix lingoand append the object modules to it by the

    following command. This will put all files ending with .o into libWrappers.a.

    ar qc l i bWr apper s. a *. o # For more on ar, simply type man ar onthe command line.

    If you are not convinced you may want to list the contents of the library.

    ar t l i bWr apper s. aChar.o

    Double.o

    ...

    ...

    UShort.o

    Now that libWrappers.a has been built, we can now place it in some fixed location and utilize the functions

    residing in it as we did in our test program.

    Using Windows

    Before you issue the following commands make sure command-line tools are made available as external

    commands. This may be easily done by executing [the commands contained in] the batch file namedvcvars32.bat found in the bin subdirectory of the Microsoft Visual C/C++ compiler.

    cl / I D: / i ncl ude / c / TC Char . ccl / I D: / i ncl ude / c / TC I nt eger . c...

    ...

    The preceding lines create the object files we need for building the library. Although rather short, they

    underline the fact that we are using a compiler-driver, not a plain compiler. In order to successfully bring in

    the required headers, using the / I option we pass the preprocessor information about places to look for

    them. Thanks to the / cwe also tell the compiler-driver to stop before linking. Finally, not really needed inour example, using / TCwe tell the compiler proper to treat the files passed on the command line as C sourcecode.

    l i b / OUT: Wr apper s. l i b Char . obj I nt eger . obj . . . # bui l ds t he l i br ar y

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    36/37

    l i b / LI ST Wr apper s. l i b # l i st s t he l i br ar y cont ent sMicrosoft (R) Library Manager Version 7.10.3077

    Copyright ( C ) Microsoft Corporation. All rights reserved.

    UShort.obj

    ULong.obj

    ...

    ...

    Char.obj

    l i b, Windows counterpart of ar, is the library-manager command. Passing different options we can get it tobuild static libraries, list library contents, and so on.

    cl / I D: / i ncl ude / FeVector _Test . exe Vector . obj Wr apper s. l i bVect or _Test . c # To get hel p on opt i ons, pass / ? t o t he cl

    / D_CRT_SECURE_NO_DEPRECATE / l i nk / NODEFAULTLI B: l i bc. l i b

    / DEFAULTLI B: l i bcmt . l i b / LI BPATH: D: / l i br ar y[11]

    Another convincing proof that cl is actually a compiler-driver! In order to get Vector_Test.exe; preprocess

    and compile Vector_Test.c and link the resulting object file with Vector.obj and needed object files fromWrappers.lib, which can be found as a result of a search starting with the location given by means of the

    / LI BPATHoption passed to the linker.

    Notes

    With the introduction of inheritance, the same container might end up having items belonging to

    different- but compatible- types.

    1.

    Nevertheless, this doesnt mean that we cannot use other techniques.2.

    Traditional C allows a variadic function with no named arguments while in Standard C there is a

    minimum of one named argument.

    3.

    Note that existing_vec is a local variable and therefore should appear in the lower part of the figure,

    just below ap to be exact. The slot marked with existing_vec actually stands for the unnamed formal

    parameter that corresponds to the second argument.

    4.

    This can be used as an argument for why a compiler may choose not to evaluate actual parameters

    from left-to-right. As a matter of fact, a right-to-left evaluation seems to be a better choice. After all, it

    is the rightmost one that gets pushed onto the run-time stack first.

    5.

    While perusing Windows source you may at times see a function name prefixed with specifiers such

    as __cdecl (C calling convention), __stdcall (standard calling convention) or __pascal. Such a specifier

    is used to tell the type of arrangement, naming convention and cleanup protocol used in the function

    call. __cdecl is used with variadic functions, while __stdcall is used for the rest.

    6.

    As a matter of fact, removing the arguments is usually no more than adjusting the stack pointer by acertain amount.

    7.

    One should also add the genericness provided through void*.8.

    If you use a visual tool this would mean adding the object files to your project.9.

    Depending on the time of linkage to the executable, a library can be either static or dynamic. The

    former brings in the object module at link-time while in the latter this is deferred to the load- or

    run-time. Our presentation in this handout will be limited to static libraries.

    10.

    This post-2005 MS Visual Studio command line reflects a non-standard aspect of the Microsoft

    compiler: in the name of making C a safer(!) programming language, compiler advisesby means of

    warningsthe programmer to use scanf _s , which is a Microsoft-only function, instead of the

    standard scanf. We ignore this by defining the_CRT_SECURE_NO_DEPRECATEmacro. Startingwith MS Visual Studio 2005, Microsoft has also removed libc.lib- single-threaded static C runtime-from its distribution. The default C runtime library that is now linked to form the executable is

    libcmt.lib, which is the multi-threaded version of libc.lib. However, for some reason, the linker may

    still end up looking for libc.lib! In order to fix this glaring glitch, using the / NODEFAULTLI Boption,

    11.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 37 20-11-2014 13:04

  • 8/10/2019 8 Programming Language Concepts Using C and C++_Generic Containers - Wikibooks, open books for an open w

    37/37

    we remove libc.lib from the list of libraries searched in the process of resolving external references

    and, using / DEFAULTLI Boption, add libcmt.lib in its place. Therefore, in a pre-2005 MS VisualStudio, this command line should be replaced with the following.

    cl / I D: / i ncl ude / FeVect or _Test . exe Vector . obj Wr apper s. l i bVector _Test . c / l i nk / LI BPATH: D: / l i br ar y

    Retrieved from "http://en.wikibooks.org

    /w/index.php?title=Programming_Language_Concepts_Using_C_and_C%2B%2B/Generic_Containers&oldid=2710822"

    This page was last modified on 6 October 2014, at 21:42.

    Text is available under the Creative Commons Attribution-ShareAlike License.; additional terms may

    apply. By using this site, you agree to the Terms of Use and Privacy Policy.

    gramming Language Concepts Using C and C++/Generic Containers... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...