ࡱ> '` objbj ^%f$EEEPhEED_HLGLGbGbGbGIIIJ_L_L_L_L_L_L_$ah{cp_PYI@IPPp_bGbG_NXNXNXPbGbGJ_NXPJ_NXNXNXbG@G fEP8NXf[_0_NXsdU sdNXsdNXIKbNXLNIIIp_p_WXIII_PPPP:T?T? Chapter 19: Handling of Arrays, Strings and Other Data Structures Up to this point, we have studied simple data types and basic arrays built on those simple data types. Some of the simple data types studied include. a) Integers: both halfword and fullword. b) Packed decimal c) Character data. This lecture will cover the following: 1. A generalized self describing array that includes limits on the permitted index values. Only 1D and 2D arrays will be considered. 2. Options for a string data type and how that differs from a character array. 3. Use of indirect addressing with pointer structures generalized to include descriptions of the data item pointed to. Structures of Arrays We first consider the problem of converting an index in a onedimensional array into an byte displacement. We then consider two ways of organizing a twodimensional array, and proceed to convert the index pair into a byte displacement. The simple array type has two variants: 0based: The first element in the array is either AR[0] for a singly dimensioned array or AR[0][0] for a 2D array. 1based: The first element in the array is either AR[1] for a singly dimensioned array or AR[1][1] for a 2D array. We shall follow the convention of using only 0based arrays. One reason is that it allows for efficient conversion from a set of indices into a displacement from the base address. By definition, the base address of an array will be the address of its first element: either the address of AR[0] or AR[0][0]. Byte Displacement and Addressing Array Elements: The General Case We first consider addressing issues for an array that contains either character halfword, or fullword data. It will be constrained to one of these types. The addressing issue is well illustrated for a singly dimensioned array. Byte Offset01234567CharactersC[0]C[1]C[2]C[3]C[4]C[5]C[6]C[7]HalfwordsHW[0]HW[1]HW[2]HW[3]FullwordsFW[0]FW[1]For each of these examples, suppose that the array begins at address X. In other words, the address declared for the array is that of its element 0. The character entries would be: C[0] at X, C[1] at X + 1, C[2] at X + 2, etc. The halfword entries would be: HW[0] at X, HW[1] at X + 2, etc. The fullword entries would be: FW[0] at X, FW[1] at X + 4, etc. Byte Displacement and Addressing Array Elements: Our Case I have decided not to write macros that handle the general case, but to concentrate on arrays that store 4byte fullwords. The goal is to focus on array handling and not macro writing. The data structure for such an array will be designed under the following considerations. 1. It must have a descriptor specifying the maximum allowable index. In this data structure, I store the size and derive the maximum index. 2. It might store a descriptor specifying the minimum allowable index. For a 0based array, that index is 0. 3. It should be created by a macro that allows the size to be specified at assembly time. Once specified, the array size will not change. In this design, I assume the following: 1. The array is statically allocated; once loaded, its size is set. 2. The array is zero based; its first element has index 0. I decide to include this base value in the array declaration, just to show how to do it. 3. The array is selfdescribing for its maximum size. Here is an example of the proposed data structure as it would be written in System 370 Assembler. The array is named ARRAY. ARBASE DC F0 THE FIRST INDEX IS 0 ARSIZE DC F100 SIZE OF THE ARRAY ARRAY DC 100F0 STORAGE FOR THE ARRAY I want to generalize this to allow for a macro construction that will specify both the array name and its size. The Constructor for a OneDimensional Array Here is the macro I used to construct a onedimensional array while following the design considerations listed above. 33 MACRO 34 &L1 ARMAKE &NAME,&SIZE 35 &L1 B X&SYSNDX 36 &NAME.B DC F'0' ZERO BASED ARRAY 37 &NAME.S DC F'&SIZE' 38 &NAME.V DC &SIZE.F'0' 39 X&SYSNDX SLA R3,0 40 MEND Line 34: The macro is named ARMAKE for Array Make. It takes two arguments: the array name and array size. A typical invocation: ARMAKE XX,20 creates an array called XX. Note the &L1 on line 34 and repeated on line 35. This allows a macro definition to be given a label that will persist into the generated code. More on the 1D Constructor 33 MACRO 34 &L1 ARMAKE &NAME,&SIZE 35 &L1 B X&SYSNDX 36 &NAME.B DC F'0' ZERO BASED ARRAY 37 &NAME.S DC F'&SIZE' 38 &NAME.V DC &SIZE.F'0' 39 X&SYSNDX SLA R3,0 40 MEND Line 35: A macro is used to generate a code sequence. Since I am using it to create a data structure, I must provide code to jump around the data, so that the data will not be executed. While it might be possible to place all invocations of this macro in a program location that will not be executed, I do not assume that. Line 36: I put in the lower bound on the index just to show a typical declaration. Line 37 This holds the size of the array. Label Concatenations in the Constructor 33 MACRO 34 &L1 ARMAKE &NAME,&SIZE 35 &L1 B X&SYSNDX 36 &NAME.B DC F'0' ZERO BASED ARRAY 37 &NAME.S DC F'&SIZE' 38 &NAME.V DC &SIZE.F'0' 39 X&SYSNDX SLA R3,0 40 MEND Recall that the system variable symbol &SYSNDX in a counter that contains a four digit number unique to the macro expansion. Line 39 uses one style of concatenation to produce a unique label. Note that in this more standard concatenation, the system variable symbol is the postfix of the generated symbol; it is the second part of a twopart concatenation. Recall that the symbol &SYSNDX counts total macro expansions. For the third macro expansion; the label would be X0003. Lines 36, 37, and 38 use another type of concatenation, based on the dot. This is due to the fact that the symbolic parameter &NAME is the prefix of the generated symbol; it is the first part of a twopart concatenation. If &NAME is XX, then the labels are XXB, XXS, and XXV. As always, it is desirable to provide a few macro expansions just to show that all of the process, as described above, really works. What follows is a sequence of two array constructions using the macro just discussed. Sample Expansions of the 1D Constructor Macro 90 ARMAKE XX,20 000014 47F0 C06A 00070 91+ B X0003 000018 00000000 92+XXB DC F'0' 00001C 00000014 93+XXS DC F'20' 000020 0000000000000000 94+XXV DC 20F'0' 000070 8B30 0000 00000 95+X0003 SLA R3,0 96 ARMAKE YY,40 000074 47F0 C11A 00120 97+ B X0004 000078 00000000 98+YYB DC F'0' 00007C 00000028 99+YYS DC F'40' 000080 0000000000000000 100+YYV DC 40F'0' 000120 8B30 0000 00000 101+X0004 SLA R3,0 Notice the labels generated. Note also the unconditional branch statements in lines 91 and 97; these prevent the accidental execution of data. The target for each of the branch statements is a donothing shift of a register by zero spaces; it might have been written using another construct had your author known of that construct at the time. Anyway, this works. Two More Macros for 1D Arrays I now define two macros to use the data structure defined above. I call these ARPUT and ARGET. Each will use R4 as a working register. Macro ARPUT &NAME,&INDX stores the contents of register R4 into the indexed element of the named 1D array. Consider the highlevel language statement A2[10] = Y. This becomes L R4,Y ARPUT A2,=F10 CHANGE ELEMENT 10 Consider the highlevel language statement Y = A3[20]. This becomes ARGET A3,=F20 GET ELEMENT 20 ST R4,Y NOTE: For some reason, I decided to implement the index as a fullword when I wrote the code. I just continue the practice, though a halfword index would make more sense. Design of the Macros The two macros, ARPUT and ARGET, share much of the same design. Much is centered on proper handling of the index, passed as a fullword. Here are the essential processing steps. 1. The index value is examined. If it is negative, the macro exits. 2. If the value in the index is not less than the number of elements in the array, the macro exits. For N elements, valid indices are 0 ( K < N. 3. Using the SLA instruction, the index value is multiplied by 4 in order to get a byte offset from the base address. 4. ARPUT stores the value in R4 into the indexed address. ARGET retrieves the value at the indexed address and loads R4. The ARPUT Macro Here is the definition of the macro to store a value into the named array. 44 MACRO 45 &L2 ARPUT &NAME,&INDX 46 &L2 ST R3,S&SYSNDX 47 L R3,&INDX 48 C R3,&NAME.B 49 BL Z&SYSNDX 50 C R3,&NAME.S 51 BNL Z&SYSNDX 52 SLA R3,2 53 ST R4,&NAME.V(R3) 54 B Z&SYSNDX 55 S&SYSNDX DC F'0' 56 Z&SYSNDX L R3,S&SYSNDX 57 MEND Note the two labels, S&SYSNDX and Z&SYSNDX, generated by concatenation with the System Variable Symbol &SYSNDX. This allows the macro to use conditional branching. ARPUT Expanded Here is an invocation of ARPUT and its expansion. 107 ARPUT XX,=F'10' 000126 5030 C146 0014C 108+ ST R3,S0005 00012A 5830 C46A 00470 109+ L R3,=F'10' 00012E 5930 C012 00018 110+ C R3,XXB 000132 4740 C14A 00150 111+ BL Z0005 000136 5930 C016 0001C 112+ C R3,XXS 00013A 47B0 C14A 00150 113+ BNL Z0005 00013E 8B30 0002 00002 114+ SLA R3,2 000142 5043 C01A 00020 115+ ST R4,XXV(R3) 000146 47F0 C14A 00150 116+ B Z0005 00014A 0000 00014C 00000000 117+S0005 DC F'0' 000150 5830 C146 0014C 118+Z0005 L R3,S0005 Note the labels generated by use of the System Variable Symbol &SYSNDX. We now examine the actions of the macro ARPUT. 108+ ST R3,S0005 Register R3 will be used to hold the index into the array. This line saves the value so that it can be restored at the end of the macro. Here we note that the generated line does not have a label; this reflects the fact that line 107, the macro invocation, is not labeled. 109+ L R3,=F'10' Register R3 is loaded with the index to be used for the macro. As the index was specified as a literal in the invocation, this is copied in the macro expansion. Were this a keyword macro, the literal would have to be specified in a different manner. This is a positional macro, which does not require special handling of literals. ARPUT: Checking the Index Value We continue our analysis of the macro. At this point, the value of the array index has been loaded into register R3, the original contents having been saved. 110+ C R3,XXB 111+ BL Z0005 112+ C R3,XXS 113+ BNL Z0005 This code checks that the index value is within permissible bounds. The requirement is that XXB ( Index < XXS. If this is not met, the macro restores the value of R3 and exits. If the requirement is met, the index is multiplied by 4 in order to convert it into a byte displacement from element 0. 114+ SLA R3,2 Here is the code to store the value into the array, called XXV. 115+ ST R4,XXV(R3) 116+ B Z0005 117+S0005 DC F'0' 118+Z0005 L R3,S0005 Line 115 This is the actual store command. Line 116 Note the necessity of branching around the stored value, so that the data will not be executed as if it were code. Line 117 The save area for the macro. Line 118 This restores the original value of R3. The macro can now exit. The ARGET Macro Here is the definition of the macro to retrieve a value from the named array. 61 MACRO 62 &L3 ARGET &NAME,&INDX 63 &L3 ST R3,S&SYSNDX 64 L R3,&INDX 65 C R3,&NAME.B 66 BL Z&SYSNDX 67 C R3,&NAME.S 68 BNL Z&SYSNDX 69 SLA R3,2 70 L R4,&NAME.V(R3) 71 B Z&SYSNDX 72 S&SYSNDX DC F'0' 73 Z&SYSNDX L R3,S&SYSNDX 74 MEND ARGET Expanded Here is an invocation of the macro and its expansion. 119 ARGET YY,=F'20' 000154 5030 C172 00178 120+ ST R3,S0006 000158 5830 C46E 00474 121+ L R3,=F'20' 00015C 5930 C072 00078 122+ C R3,YYB 000160 4740 C176 0017C 123+ BL Z0006 000164 5930 C076 0007C 124+ C R3,YYS 000168 47B0 C176 0017C 125+ BNL Z0006 00016C 8B30 0002 00002 126+ SLA R3,2 000170 5843 C07A 00080 127+ L R4,YYV(R3) 000174 47F0 C176 0017C 128+ B Z0006 000178 00000000 129+S0006 DC F'0' 00017C 5830 C172 00178 130+Z0006 L R3,S0006 The only difference between this macro and ARPUT occurs in line 127 of the expansion. Here the value is loaded into register R4. Note that, in the sequence of macro expansions, ARPUT was expansion number 5 and ARGET was expansion number six; hence the labels here are S0006 and Z0006 rather than S0005 and Z0005. RowMajor and ColumnMajor 2D Arrays The mapping of a onedimensional array to linear address space is simple. How do we map a twodimensional array? There are three standard options: The two that we shall consider are called rowmajor order and columnmajor order. Consider the array declared as INT A[2][3], using 32bit integers, which occupy four bytes. In this array the first index can have values 0 or 1 and the second 0, 1, or 2. Suppose the first element is found at address A. The following table shows the allocation of these elements to the linear address space. AddressRow MajorColumn MajorAA[0][0]A[0][0]A + 4A[0][1]A[1][0]A + 8A[0][2]A[0][1]A + 12A[1][0]A[1][1]A + 16A[1][1]A[0][2]A + 20A[1][2]A[1][2]The mechanism for Java arrays is likely to be somewhat different. Addressing Elements in Arrays of 32Bit Fullwords Consider first a singly dimensioned array that holds 4byte fullwords. The addressing is simple: Address ( A[K] ) = Address ( A[0] ) + 4(K. Suppose that we have a two dimensional array declared as A[M][N], where each of M and N has a fixed positive integer value. Again, we assume 0based arrays and ask for the address of an element A[K][J], assuming that 0 ( K < M and 0 ( J < N. At this point, I must specify either rowmajor or columnmajor ordering. As FORTRAN is the only major language to use columnmajor ordering, I shall assume rowmajor. The formula is as follows. Element offset = K(N + J, which leads to a byte offset of 4((K(N + J); hence Address (A[K][J]) = Address (A[0][0]) + 4((K(N + J) Suppose that the array is declared as A[2][3] and that element A[0][0] is at address A. Address (A[K][J]) = Address (A[0][0]) + 4((K(3 + J). Element A[0][0] is at offset 4((0(3 + 0) = 0, or address A + 0. Element A[0][1] is at offset 4((0(3 + 1) = 4, or address A + 4. Element A[0][2] is at offset 4((0(3 + 2) = 8, or address A + 8. Element A[1][0] is at offset 4((1(3 + 0) = 12, or address A + 12. Element A[1][1] is at offset 4((1(3 + 1) = 16, or address A + 16. Element A[1][2] is at offset 4((1(3 + 1) = 20, or address A + 20. Here is a first cut at what we might want the data structure to look like. ARRB DC F0 ROW INDEX STARTS AT 0 ARRCNT DC F30 NUMBER OF ROWS ARCB DC F0 COLUMN INDEX STARTS AT 0 ARCCNT DC F20 NUMBER OF COLUMNS ARRAY DC 600F0 STORAGE FOR THE ARRAY NOTE: The number 600 in the declaration of the storage for the array is not independent of the row and column count. It is the product of the row and column count. We need a way to replace the number 600 by 30(20, indicating that the size of the array is a computed value. This leads us to the Macro feature called SET Symbols. SET Symbols The feature called SET Symbols allows for computing values in a macro, based on the values or attributes of the symbolic parameters. There are three basic types of SET symbols. 1. Arithmetic These are 32bit numeric values, initialized to 0. 2. Binary These are 1bit values, initialized to 0. 3. Character These are strings of characters, initialized to the null string. Each of these comes in two varieties: local and global. The local SET symbols have meaning only within the macro in which they are defined. In terms used by programming language textbooks, these symbols have scope that is local to the macro invocation. Declarations in different macro expansions are independent. The global SET symbols specify values that are to be known in other macro expansions within the same assembly. In other words, the scope of such a symbol is probably the entire unit that is assembled independently; usually this is a CSECT. A proper use of a global SET symbol demands the use of conditional assembly to insure that the symbol is defined once and only once. Local and Global Set Declarations Here are the instructions used to declare the SET symbols. TypeLocalGlobalInstructionExampleInstructionExampleArithmeticLCLALCLA &F1GBLAGBLA &G1BinaryLCLBLCLB &F2GBLBGBLB &G2CharacterLCLCLCLC &F3GBLCGBLC &G3Each of these instructions declares a SET symbol that can have its value assigned by one of the SET instructions. There are three SET instructions. SETA SET Arithmetic Use with LCLA or GBLA SET symbols. SETB SET Binary Use with LCLB or GBLB SET symbols. SETC SET Character String Use with LCLC or GBLC SET symbols. The requirements for placement of these instructions depend on the Operating System being run. The following standards have two advantages: 1. They are the preferred practice for clear programming, and 2. They seem to be accepted by every version of the Operating System. Here is the sequence of declarations. 1. The macro prototype statement. 2. The global declarations used: GBLA, GBLB, or GBLC 3. The local declarations used: LCLA, LCLB, or LCLC 4. The appropriate SET instructions to give values to the SET symbols 5. The macro body. Example of the Preferred Sequence The following silly macro is not even complete. It illustrates the sequence for declaration, but might be incorrect in some details. MACRO &NAME HEDNG &HEAD, &PAGE GBLC &DATES HOLDS THE DATE GBLB &DATEP HAS DATES BEEN DEFINED LCLA &LEN, &MID HERE IS A LOCAL DECLARATION AIF (&DATEP).N20 IS DATE DEFINED? &DATES DC C&SYSDATE SET THE DATE &DATEP SETB (1) DECLARE IT SET .N20 ANOP &LEN SETA L&HEAD LENGTH OF THE HEADER &MID SETA (120-&LEN)/2 MID POINT &NAME Start of macro body. A Constructor Macro for the 2D Array This macro uses one arithmetic SET symbol to calculate the array size. Note that this definition does away with the base for the row and column numbers, as I never use them. 30 * 31 * MACRO DEFINITIONS 32 * 33 MACRO 34 &L1 ARMAK2D &NAME,&ROWS,&COLS 35 LCLA &SIZE 36 &SIZE SETA (&ROWS*&COLS) 37 &L1 B X&SYSNDX 38 &NAME.RS DC H'&ROWS' 39 &NAME.CS DC H'&COLS' 40 &NAME.V DC &SIZE.F'0' 41 X&SYSNDX SLA R3,0 42 MEND Here are two invocations of the macro ARMAK2D and their expansions. 86 ARMAK2D XX,10,20 00004A 47F0 C36E 00374 87+ B X0009 00004E 000A 88+XXRS DC H'10' 000050 0014 89+XXCS DC H'20' 000052 0000 000054 0000000000000000 90+XXV DC 200F'0' 000374 8B30 0000 00000 91+X0009 SLA R3,0 92 ARMAK2D YY,4,8 000378 47F0 C3FA 00400 93+ B X0010 00037C 0004 94+YYRS DC H'4' 00037E 0008 95+YYCS DC H'8' 000380 0000000000000000 96+YYV DC 32F'0' 000400 8B30 0000 00000 97+X0010 SLA R3,0 Please note the hexadecimal addresses at the left of the listing. Line 90 corresponds to byte address X0054 and line 91 to byte address X0374. The difference is given by X320, which is decimal 800. Line 90 reserves 200 fullwords, which occupy 800 bytes. The storage allocation indicated by lines 96 and 97 is similar. Line 96 sets aside thirtytwo fullwords, for an allocation of 128 bytes. X400 X320 = X80 = 128 in decimal. The ARGET2D and ARPUT2D macros would be based on the similar macros discussed above. Each would take three arguments, and have prototypes as follows: ARGET2D &NAME,&ROW,&COL ARPUT2D &NAME,&ROW,&COL Each macro would insure that the row and column numbers were within bounds, and then calculate the offset into the block of storage set aside for the array. The writing of the actual code for each of these macros is left as an exercise for the reader. Strings vs. Arrays of Characters While a string may be considered an array of characters, this is not the normal practice. A string is a sequence of characters with a fixed length. A string is stored in string space, which may be considered to be a large dynamically allocated array that contains all of the strings used. There are two ways to declare the length of a string. 1. Allot a special end of string character, such as the character with code X00, as done in C and C++. 2. Store an explicit string length code, usually as a single byte that prefixes the string. A single byte can store an unsigned integer in the range 0 through 255 inclusive. In this method, the maximum string length is 255 characters. There are variants on these two methods; some are worth consideration. Example String In this example, I used strings of digits that are encoded in EBCDIC. The character sequence 12345 would be encoded as F1 F2 F3 F4 F5. This is a sequence of five characters. In either of the above methods, it would require six bytes to be stored. Here is the string, as would be stored by C++. Byte number012345ContentsF1F2F3F4F500Here is the string, as might be stored by Visual Basic Version 6. Byte number012345Contents05F1F2F3F4F5Each method has its advantages. The main difficulty with the first approach, as it is implemented in C and C++, is that the programmer is responsible for the terminating X00. Failing to place that can lead to strange runtime errors. Sharing String Space String variables usually are just pointers into string space. Consider the following example in the style of Visual Basic.  Here, each of the symbols C1, C2, and C3 references a string of length 4. C1 references the string 1301 C2 references the string 1302 C3 references the string 2108 Using Indirect Pointers with Attributes Another string storage method uses indirect pointers, as follows. Here the intermediate node has the following structure. 1. A reference count 2. The string length 3. A pointer into string space. There are two references to the first string, of length 8: CPSC 2105. There are three references to the second string, also of length 8: CPSC 2108. There are many advantages to this method of indirect reference, with attributes stored in the intermediate node. It may be the method used by Java. There are a number of advantages associated with this approach to string storage. In general the use of indirection in pointers, as illustrated above, simplifies system programming. Here are a few illustrations of some of the standard considerations: 1. If pointer P1 is deallocated, the reference count for the string CPSC 2105 is reduced by 1, but the string is not removed. 2. If pointer P2 is deallocated, then the reference count for the string goes to 0, and the string space can be reclaimed. Reclamation of dynamic memory (string space in this example) is a tricky business and often is simply not done. However, the existence of the intermediate pointer facilitates such an operation. Suppose that the string CPSC 2105 is removed and the string CPSC2108 is moved up by eight positions. There is only one value that needs to be reassigned, and it is not the addresses associated with pointers P3, P4, or P5. It is the address in the intermediate node that each of P3, P4, and P5 reference. This intermediate node is easy to locate.     Page  PAGE 367 Chapter 19 Revised August 3, 2009 Copyright 2009 by Edward L. Bosworth, Ph.D. S/370 Assembler General Arrays and Strings  ABh, R S W -  ! {  4 S .?p$)0@LtɻɻwwhrhrCJaJh=$hrCJaJ hChr hChGhChG5 h=$5hr hChhCh5 hChq hChm] hChhm hCh@NXhmh`5CJaJhmhm]5CJaJhmh+Q!5CJaJ.B  , S 1 P ~ ?$024$ h$Ifa$gdC hxgdrgd=$ hxgdm hgdCgdm $ha$gdmno468:<>@ALQV[`ejotuFfQFf$ h$Ifa$gdCJ888$ h$Ifa$gdCkdR$$Iflr l,   t044 laytrCD$FOx &Ebc|4GHüø~wpw hCh<4 hCh~:<hChV;5hCh~:<5 hChahCh[5OJQJ^JhCh25OJQJ^J hCh2h  hCh - hChlmhFWH h=$5hChZU5 hr5 hChG hChZU hChrhrhrCJaJ+DpdXNNNIIgdr hgdC hxgdRV* hxgd=$kd$$IflFl   t0    44 laytrO cb^24Ht$P|gdCgd=$ hxgd  hgdCgdrHt0<UWXYcf ai )+Qp4[\۽۽۶ɯɯɯ}l hChQz5B*OJQJphhChQz5 hCh 5B*OJQJphhCh 5 h 5hChQz5OJQJ hChQz hCh<4hCh 5OJQJh hCh 5OJQJ^J hCh  hChST 5B*OJQJphhChST 5OJQJ*Y 5a=i 4\ 8dgd=$ hxgd xgd gdCgd  hgdC hxxgd 9 !""";#y###3$q$$$+%i%%'5'' hxgdz|xgd&@xgd gd=$ hgdC hxgdDZ hxgd gdC{: A f !!!|!!!!!!!!!!!!!""""")$2$3$q$%֨vivvh 5CJOJQJaJh=$hW5CJOJQJaJ(h=$hW5B*CJOJQJaJphhChW5 h 5 hChDZh2hCh25OJQJ^J hCh2hChDZ5OJQJ^JhDZh hChQz5OJQJ^J hChQzhChQz5OJQJ&%%'''5'V'w''''''''''' (+(V(`(o(v(w(z((((((((((())) )6)R)j)u)))))))۽۽۽׽۽۽ۛۛ۔ی~hCh;c5OJQJ^JhCh;c5 hCh;chRhR5OJQJhz|5OJQJhCh;c5OJQJhCh` 5OJQJhCh` 5OJQJ^Jhz| hCh` hCh` 5 hChWh"h&@ hChVMu1'b(w((() )))**[++,Q,b,,,,-1-R-s---gdC hxgdgd=$ hxgdR hgdC))* *5*K*R+S+i+l+++,,Q,R,a,b,n,x,,,,{........./ ///9/H/M/_/a//ꩢwgh=$hO5CJOJQJaJhChs5OJQJhChx@5 hChshzhChx@5OJQJ hChx@hChuC=5OJQJ hChuC=h$qhCh;c5hChuC=5 h5 hh;c jhCh;ch hCh;chCh;c5OJQJ^J(---.9.Z.{. ///a///'0i000/1q11172y22323 hxgdzgd=$ hgdCxgdzgdC////a0d00000$1)11111_2d2222222222333+30323H3M3O3}333b4c444445"5555ۿhz hChl5B*OJQJph hChx@hChl5OJQJ hChl hChHa5B*OJQJph hChHa(h=$hO5B*CJOJQJaJphh=$hO5CJOJQJaJ(h=$hO5B*CJOJQJaJph123P3c445566667L7w728P8888893999 8xgd$qxgd$qxgdzgdC hxgdzgdzxgdz hgdC55(6C666666666677d7g7h7i7r7u7w7777728P8888888888888999Y9w99 :!:󾲫||h$q hChz5O5B*OJQJphhChz5O5OJQJhChz5O5OJQJ^J hChz5OhChN95OJQJ hChN9 jhChN9 hChl5B*OJQJphhChl5OJQJ hChlhzhChl5/9!:1:::::;$;E;f;;;;; <,<M<N<^<<<=Z== hgdCgdC hxgd$qgd=$ 8gd$q!:1:=:G:}::M<N<O<^<<<<======>>W>\>>>?"?P?U??????????-@_@d@@@@@@@@̼yyyyyh^"h^"5OJQJ^Jh^" hCh%(h=$h%5B*CJOJQJaJph(h=$h%5B*CJOJQJaJphh=$h%5CJOJQJaJ hChhCh5 h$q5hCh5OJQJ hCh}|h$qhCh}|5/== >b>>>(?j??@AAB4C*hCh[5OJQJ^J hCh[! jhChD5OJQJ^JhChD5OJQJ^J hChDIQJRJvJJJJJJ"K#K;KBKcKKKKKKL0LLLHMIMRMSM^McM}MMM"NbNhNNNNOOPO}OOOOO2P3P Q,QQQQR#R$RRRqRFThTTT hCh~1nhCh~A5h& hCh~AhY hChDbhCh!l5 hh5 hCh!l hCh[ jhChhh hChhCh5;ZM^NPOOO3P8P>PEP$ h$Ifa$gdC h$IfgdC hgdCgdh hxgdhEPFPGPSP[PgPoPn_MMMM$ h$Ifa$gdC h$IfgdCkd $$IflF ! x t06    44 laytYoPpP{PPPH9''$ h$Ifa$gdC h$IfgdCkd $$Iflr5  !_p t0644 laytYPPPPP6' h$IfgdCkd $$Iflr5  !_p t0644 laytY$ h$Ifa$gdCPPPPPP6kdj $$Iflr5  !_p t0644 laytY$ h$Ifa$gdCPPPPPP$ h$Ifa$gdC h$IfgdCPPxQQQH:.. hgdC hxxgdYkd $$Iflr5  !_p t0644 laytYQ$RRR7S]SSSS2TFThTTTUGU|UUUV=VKV~VVVgd=$ hxgd& hgdC hgd&TUU-UFUGUUUVVVV1WWWY#Z*Z@ZAZZ9\\\\]Q^R^X^u^v^üygygXgMMh5OJQJ^Jh5CJOJQJ^JaJ#h]Vh5CJOJQJ^JaJ,hh5B*CJOJQJ^JaJphhMhh5OJQJ^JhhMhM5OJQJ^Jhb_h^m hCh hCh~1n5hChb_5 h&5h&5OJQJ^JhCh$5OJQJ^JhCh~1n5OJQJ^JVVWWW'XVXXXXYAYpYYYYAZZZ[a[[[9\\\gdgdgdM hxgdMgd=$\]Y]]]^_>`z`waaabccdUdddeeee$ h$Ifa$gdC hxgd& hgdCgd=$ hxgdMxgdgdv^|^^^^}_____________>`D`\`b`z`vawaxaaaaa b.bDbRbSbrbbbFcKcccccUdddŷŷ~w hChtBChChIf%5OJQJ^Jh& hChIf%hCh 5hChIf%5 h? 5 hCh? h? h? h? 5OJQJ^Jh? 5OJQJ^Jh^mh^m5OJQJ^Jh^mh5OJQJ^Jhhh5OJQJ^J.dddd ee&e4e7eceeeeeffffff f#f(fpfrfsfufvfxfyf{f|f~ffffffffg.g3gGgTgpgqggggghhh̾𶮧jh=$UmHnHu hChb hChi hCh,WhCh&x5hChb5hCh&x5OJQJ^J hCh&x hCh>Fh=$hChGZ5OJQJ^Jh& hChGZhChtBC55eeeeee$ h$Ifa$gdCee"kd $$Ifl֞$ \ d  88 t0644 layt=$eeeefff f$ h$Ifa$gdC f fNf" hxxgd&kdo $$Ifl֞$ \ d  88 t0644 layt=$NfZf\f^f`fbfdfff$ h$Ifa$gdCffgf"kd&$$Ifl֞$ \ d  88 t0644 layt=$gfpfsfvfyf|fff$ h$Ifa$gdCffqg" hxgd&kd$$Ifl֞$ \ d  88 t0644 layt=$qgghhhNhnhhhhhhhhhhiiYiii?j@jjj hxgd{ hgdC hxgd[gd=$hhMhNhmhnhhhhhhhhhii iXiYiii>j?j@jjjjjnnnnnooooo o ooooo簩zohC0JmHnHu hU_0JjhU_0JUh2Ojh2OU hChU_hU_h h8%I hCh-+ hCh hCh jh=$UmHnHu hChv\hCh{5hChv\5h{ hCh{ hCh,W hChihC+jjkXllnnnoooooojokooooo hxgdU_ hgdCo,o4oioooo hChU_h2OhU_ hC0J hU_0J901hPm:pC/ =!"#$% 21h:p$/ =!"#$% @= [4?\٤?%L0 ,Dxݻ4up5806wB7;vpH:љ!( 6hM ]3})U!ꛞWŪa_R(J7JR/'I:߻Կ~RJ2ϔO /oXF9/R?gX>||[?__o_V;o_Ο~2 w~g9Vr#0_FFFFF9RP~P~@ty_AAArQ~DGG㛲(((~<x,(?uB 'P~B WX_,rz~ _ïOl _ïO~ _ïk_ïk5Ӫ_ïk5i5ïk5~ yh5~ _ïޯ?m{ io7 ~7` @I7 ~x2es SUo7 o7 ~  ~ovImjo[-~ T[-~ [-~ ?UW-~ f᧪ o[-S5LJ ofO7^켞+|$8 v:?tcwg_/~wdLJaY1?8+WW!/p [:ᇹlj_|?j5yUЯj9l{/~C\"׿/~񋟷)qHX?CW|kGcobퟷd/n~żgw L?=[ߡ__?oz6mχ?{񋟅__+e?'bP 㿋/~Ŀe;=?I'z(|Q3^~f_uW,?Π/פ?cy9FDy?s??X1{YSέ:;_?dkw>!>!||8;2;2{^(8D޿e'|ڟ߾R+⟡`$~?Cl\ aX"??:.NDWwd~Z͟swx_OO׿>w/?sÿ8w'+(jX|)/a&GoJ;'O/ O{㿊モo'&~=? wWeW z}OuN~Ot_%^~b;VZwچ#!x_&x6/|wן/Nseӟ/=s+JRV:s^~w5ޟ*ޟW??__O_n/OƿBߍl-_]㋿A~ߒ|Ee'/̧/͟פ?Ͽ87?cy9z +<5oW'bW__)~+/Su5~04ݼAjG8'P[>|n~u&-wf|~aJ|Jrk'O߅/Kgw{dTTƿ໔ן'2M ^Y{o;>.)l| 3g\_r]kwns]߶7q||cw,KПrWgg{~+?~~}Z~*wn~2t`?GweWPP;7O}~3踸M~J'WV?)~Z3?y >k3*n"~߮ _9{%O'wpS?O9 m(O? ~Okӫ]n'?ɺxwfYoJ˜z˽zs?_Wϫh4şVOѠx_Ie=Qat ǿU秏 fɜ>?}oq%MۿkV5Zl'ƿS8Hk_.soO:ois~מO_.P@_0wdP߭ۋ^qu!W߭ZZ~׻xk~38ǿp|_SC?i???ߋZsJϩ+?ꯔfGĶg_;ZR/~we#פ?Octs7?O;2G7cy /%?wwniLW?~ğw9W?Ԇ_,ڿ'Pb__̮\ $_{K?ˍӥ|s,_` 7/JG~>8sXzQ;gxgp{Uxo~eߛO;Ze_/b9)~ł;xHP~@?P~@}QnPngP師(?#ʏx#MY[[??<:O(?c`9bXNoWïk5_Ҹk5ik5~ k5~ Zk5~ _?f5~ _ï?o _ïk5ouRm?m ~o6~C|076)~o7OobBlu~  ~?U ~o?W!o7 SN[0-v:U--~ o៪~ oOU~ o[ o@[,>T[-~ ,^Iƫyzce/2/~_,eOdǯu!NϯB~CR\ Yz?Zר!;_?dkw>!>!||8;2;2{^(8D޿e'|ڟ߾R+⟡`$~?Cl\ aX"??:.NDWwd~Z͟swx_OO׿>w/?sÿ8w'+(jX|)/a&GoJ;'O/ O{㿊モo'&~=? wWeW z}OuN~Ot_%^~b;VZwچ#!x_&x6/|wן/Nseӟ/=s+JRV:s^~w5ޟ*ޟW??__O_n/OƿBߍl-_]㋿A~ߒ|Ee'/̧/͟פ?Ͽ87?cy9z +<5oW'bW__)~+/Su5~04ݼAjG8'P[>|n~u&-wf|~aJ|Jrk'O߅/Kgw{dTTƿ໔ן'2M ^Y{o;>.)l| 3g\_r]kwns]߶7q||cw,KПrWgg{~+?~~}Z~*wn~2t`?GweWPP;7O}~3踸M~J'WV?)~Z3?y >k3*n"~߮ _9{%O'wpS?O9 m(O? ~Okӫ]n'?ɺxwfYoJ˜z˽zs?_Wϫh4şVOѠx_Ie=Qat ǿU秏 fɜ>?}oq%MۿkV5Zl'ƿS8Hk_.soO:ois~מO_.P@_0wdP߭ۋ^qu!W߭ZZ~׻xk~38ǿp|_SC?i???ߋZsJϩ+?ꯔfGĶg_;ZR/~we#פ?Octs7?O;2G7cy /%?wwniLW?~ğw9W?Ԇ_,ڿ'Pb__̮\ $_{K?ˍhˏ2q3\> uG!_]?UY@=& }x'bEKH%x͎U:䆄s 0@b$H!8˗_8G8ᯝ~_wn_uG*YUo9EkOo?gM>~ǯo8_|?p[_o}r?uvno+Wp[o}tOE]׮YeTx,,Z/$,dy%+Y.O'Y$˟'Y$˟dߕ^v^{Y|۸Y?gY,O>gY.\-kY^Ϸ,EY"_d,yy]}IOxG->r++۰*++M"W%W%W%K$J$J$Jo7_I_I_Inf+++FPI_I_I_IޟڨK^K#{K^߲I^[RK^%[_=({K[A%~/{}H^%~/B^%~/{}Hu+F]Ku%---o;kkk}KJ_K_K_KU%Z%Z%ZV}+K_K_K_K\V kyW t.]nnOݾV0ÌYʯ~ݫ1Ìy0o 3(af0 +Sz{"0jp!f90lebfrf;׻h5Ԕ37lEϞ13[TJ7r̲icfy0+c0;ج?7rolN(aaf¾faF 30cV13mvYfw%?G 3r3Yif̆g՘Q(0X㜺~̊3G\q-Ƥ`&yg^f083`FaH 30`fTBL3mK5c߈k906sf0+,o3F4sM̌GY`f,afǛazF͉30Ì}#30Ì2skj$fY6b3 gaf3ff3Kf#fʹ?fV)=1+CYv#f%fA\A}3熭ILuc `lͫ1ÌfaF 3,1.3 F faks-ƨ5ψ#< unqY*u:13c ~b1 d0;ybFmFނ̸z6qv<9in֭hC> ͺIڍ&hLM=j̘891`fQ0;b0o`fQ0;UNJ 3l"{#fz`VYʠA ŧ̐:+fǧY ?1K3+fNb;ΩKk7bV` fA\Ay33>SN0;ll&-%f׳͉30Ìى}#30ÌfaFYkg13X>UTfq4L)hY7N%Yfc3&07 SL[aV9utfBoI3;fѡLY6?03i6zSYl1ÌfgƸ()af.af(cQ+hGI5h94ʙ3Sn B1eΆ7̈Y$3f^0+Ejy'px9[YVϮ3gnfOlT9ig5~ޝzw6vf͆RV @q똭{u)uԑ1vc㸉jvFo,6S4˷E13f6c\ fg0Ⱦ3h`faqf#3hcv|=F],փo__7\ì~C3ck?vȢh6_Ьy7kf3aV5kfMъ2'fcĤߗ6[GDv=`60r~5Kxg[%rfΩA[?rvx?HJ+SkW9J3ҺY81s٣OL믬'5} faf{1.31.37bfY^0+K7-0ۙK&Þ}+ @Sn/,l,fvةwh7X+L 7+vS?o63L=Ι1{)L#שfs c)ş-v\9tl29SqfV Ff6'sghLt?9@Ul)5exfŬْi$xۙԖ2[8Pl\4K'iiFN)}įhMcѺي9uDʵ>Ҭ7-C}@L5Oj\Y;eUnus@ fK;\ʾlVfqGH7p/qTfw1U Em?.&ҿz\XPf6{ ȟ⸘Y h/ &`=nFaۍsvGfna69qXOb;/.^,vΚbjAF|h={qM&|a=ӧI+׿%~07w<{p;ld;nq7h)'B8,m7J,Y.Y"v*2̭7C/vJfM܄)fIl(v>َb)?êibyڍ&K6n왥d+6Mfl,25ӡfsHpIQ;5)[}ld̑!W2[)~8*Y(f\ bf/"f 1uۜgAFّfs]IqnAfصȬ-wfG-cbu4=[- ٠o#od_S,,5k`%tHKŮJl^Rr6i,r%1 `XV+ߚif2aMf0i Ls#dճ0{۷'WFl,5I7Clv<۸vn1ti+u[<| D3熭Ʌf D3)bZyƆX̘{$f97&d߈3/:f_=ۨ Vb[, no\ b[,n߈Xiffn83J3Cl: |y-.7{q̖ fA\ϐX|DP|fט9}6f6 !nn1 1fX# xP63[pwIԳ M3 -;v5mb[u+ڐoQ$bfЬ;tkhL cǍPbr8ݖ"d%uօZ, r:?k4476~\0Ff1Y7R0`fQflu5:fDFLn-A6OuF-e2aVY|f ̘%sR:w4K3+fN}}>u.fe5ΩnĬL.fpS˱fWן0P;Ԭ7L9޾qmoJW<PVҫAt655Ljc\vx1f#jv27/SQf]50{lo,seì 72<չOfvΚ5oAf;`6:{ 5I,HcPw1 MSQf2Y_;{_¬)잜&j6GEsHՒIm9A2˨E[cVZzxnZL6%W{mY3l,0ˣ6b6^?=m9m 56WD,K9YO]+ۘy,Y".lƩӦhfS.x6lSfjئ\YoXmY9_[n-84OZs, s'eOc|\]M2͓,kƟ d4`ؘiu~^f:sLkv8xmn3=2#j(=cm뱹oйqed|`{fSf;m$g>D37jѾq7fEl؟z7 4A[S? >#h=rڍzQGƸ^TrMP&03aqfe#Y/D)fnjaVj[zfZFo+njRǷNߕǷ y|Kߑ׿p>8M_u{'yT/u?_~͹ǏOw~Cw޿~/vjO~(ǓL-_;8lW\bICgʬ0/̝,=hhլ0ldZafs2O1q~VDßS ]^KRSFgVJ<-FyNm(~ 昙5 @{NtfG4SmN\ #zB0Gn$]Tj١f?hȵSV5ތQBl^= y}{rUgfœ\.}3vj73 kwk\laNm}nA\1;+K4snؚ\h&hk K49c"fllŌGbfa y0˘ssnJfLM1xsivճ b!V VfXif3C43Ėgrkl9[nֹ8 G w>ojnq'ncjbfa5k;,-o`7;e3~?~7K= a@ \m}-<ΐbsj7Y!Y A"fl ͺIƬa˴p W6 2{S+l0SdfaYnfhzȫGYQhݐ^R)7ut>ev!S_U+̚2ifc}+[4t\-ږd+jQ5f &aSrf5I lmeK;p Y-8J.Zz1f]f$~O V_vfѡLG/܅$^9l㩗ĒxSYvĽrv??Ro&w@ނA}Ojc]͊ o*wTk{7;0Kꪟm\ӂC92;:wRd?,;>^`,<9 9ʲ&)hYܠQ~KF ]e/OFѶ; +h3M~@ALQV[`ejotuD   O c b  ^ 2 4Ht$P|Y 5a=i 4\ 8d9;y3q+i5b w ! !!!""[##$Q$b$$$$%1%R%s%%%%%&9&Z&{& '/'a''''(i(((/)q)))7*y**+2+P+c,,--..../L/w/20P0000013111!21222223$3E3f33333 4,4M4N4^4445Z555 6b666(7j77899:4;<;F;S;T;V;^;f;g;m;u;};~;;;;;;;;;;;;;;;;;<Q<<=>>>?n???#@c@@@)AtAAAA BMBBCC\DDD"EZE^FPGGG3H8H>HEHFHGHSH[HgHoHpH{HHHHHHHHHHHHHHHHHHxIII$JJJ7K]KKKK2LFLhLLLMGM|MMMN=NKN~NNNNOOO'PVPPPPQAQpQQQQARRRSaSSS9TTTUYUUUVW>XzXwYYYZc[\U\\\]]]]]]]]]]]]]^^^ ^ ^N^Z^\^^^`^b^d^f^g^p^s^v^y^|^^^^q__```N`n``````````aaYaaa?b@bbbbcXddfffggggggjgkgggg0000000000000000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00000000000000@00@0000@0000000000000000@0@0@0@0@0@0@000000@0@0@0@0@0@0@0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@0@0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @000000000000000000000000000000000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 000000000000000000000000000000@0@0@0@0@0@0@0@0@0@0@0@000@0@0@0@0@0@0@0@0@0@0@0@00000000000000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0@0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 @0 00000000000000000000000000000000H0000H0000000000@00 0 L@000008$P 8d3q9&Z&/)/ 4,4M4j77PPQAQpQQQQUYUUU^q__```aagZ00Z00Z00@0Z00Z00Z00@0Z00Z00Z00@0Z00/Z00Z00@0Z00/Z00@0@0Z0 0 /Z0 0Z0 0Z00/Z0000000 X0 0 X000! "lX000X00Z00 Z00Z000Z0#0$ Z0#0000 ppppH%)/5!:@E\GQJTv^dhoo8=@CDFHJLNVXYbefpr4'-239=SCfC}CCCCCFZMEPoPPPPPQV\eee fNfffgffqgjo9;<>?ABEGIKMOPQRSTUWZ[\]^_`acdghijklmnoqo:!/X"$ [4?\٤?%Lo"$ }x'b &S@N(  V  # A3"`V  # A3"`B S  ?`ag T*T# #!#"###$# %#T&#2'#L(#)#*# +#D,#4-#|.#\/#D0#1#̯2#3#lF4#F5#G6#TH7#I8#I9#tJ:#$K;#K<#L=#4M>#M?#N@#TA#-B#d\p&!!$$%`),Z,Z,?0223688(G(GOOQ"TU W WXXvXvXAcAcg      !"_ s)!!$$%c),^,^,B0223688+G+GOOQ%TU W W[XyXyXDcDcg  !"9#*urn:schemas-microsoft-com:office:smarttagsplace;*urn:schemas-microsoft-com:office:smarttagsaddress9*urn:schemas-microsoft-com:office:smarttagsState8*urn:schemas-microsoft-com:office:smarttagsCity:*urn:schemas-microsoft-com:office:smarttagsStreet X#####################fffffffffgggggg gg,g4ggg  df(2bd9<YMO#%<Fvx,.mpV Y o v ! !$$%%$%&%E%G%%%%%%%M&O&''''( (`(d(((h)j)))**G+M+x,z,)-/-....G0I0000122222233Y3[333334!44455Q5S55566666677:!:<<====>>?w?y?????+@-@k@m@@@@@NNrPtPwQQQQ|RR(T*TtTxTUUQXSXsaaaafffffffffgggggg gg,g4gZggg3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333$@Atu< b 4\qw+ b .#[#R%s%&8&& 'c,,..00,4M4O4^44;;0D]DGG3HEHGHH^KK3LELLLMPM}WW7]_]] ^N^^q__bbffffffffgggggg,g4gggffffffggggggggX45*L`  ?   iB ST j f ;oCo Km./[Gsxy +Q!^"=$If%&)&F&7(%>)Up)RV*i*-+";+^a+j-QH.:1^1>2<4Y5#839N9O+:`P: ;V;~:<uC=&@x@A~A\BCtBC>FGlIGFWH8%IDqL$M\Mz5ORRUZUl_U,W@NX~Y ZM2ZDZGZm]CoaDbjSb;cleMkl!l^mlm~1nPo$q;rtBt=VtuVMuTwQzz|Yz=hQ L2Dq( {:GY{$,1Q U_: -D 2OD`WmMIcWr.[JzL m,v\ hb$bms[&rzcXqz{@&x2_V*i}|7(`%;&aO5b_cgcU<q"HaW$02468:<>@ALQV[`ejotu4;<;F;S;T;V;^;f;g;m;u;};~;;;;;;;;;;;;;;;;;3H8H>HEHFHGHSH[HgHoHpH{HHHHHHHHHHHHHHHHHH]]]]]]]]]]]]^^^ ^ ^N^Z^\^^^`^b^d^f^g^p^s^v^y^|^^^^g@BBPBBgP@UnknownGz Times New Roman5Symbol3& z Arial?5 z Courier NewQTimes New Roman Bold"1 hzf_&!t^W4^W4%4dff2QHX ?&25Handling of Arrays, Strings and Other Data StructuresEdward L. Bosworth, Ph.D.Edward L. Bosworth, Ph.D.Oh+'0 4 Xd   8Handling of Arrays, Strings and Other Data StructuresEdward L. Bosworth, Ph.D. Normal.dotEdward L. Bosworth, Ph.D.33Microsoft Office Word@{4@,Yc@ʥ^W՜.+,04 hp  Columbus State University4f' 6Handling of Arrays, Strings and Other Data Structures Title  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry FData 1TablesdWordDocument^%SummaryInformation(DocumentSummaryInformation8CompObjq  FMicrosoft Office Word Document MSWordDocWord.Document.89q