510 likes | 1.13k Views
Arrays and Pointers. Concepts to Learn…. Arrays C Strings Array Arguments Pointers Null Pointers Pointer Arithmetic Arrays and Pointers Static Variables Parsing C I/O Pointers to Pointers Multi-dimensional Arrays Command-line Arguments. Arrays. Arrays.
E N D
Concepts to Learn… • Arrays • C Strings • Array Arguments • Pointers • Null Pointers • Pointer Arithmetic • Arrays and Pointers • Static Variables • Parsing • C I/O • Pointers to Pointers • Multi-dimensional Arrays • Command-line Arguments
Arrays Arrays • An array is a sequence of like items. • int’s, float’s, long’s, • Like any other variable, arrays must be declared before they are used. • General form: type variable-name[number_of_elements]; • The array size must be explicit at compile time – needed to reserve memory space • Array elements individually accessed with index. • General form: variable-name[index]; • Zero based subscripts • No compile-time or run-time limit checking
Arrays Initialization of Arrays • Elements can be initialized when they are declared in the same way as ordinary variables. • type array_name[size] = { list of values separated by commas }; int number[3] = {0, 0, 0}; • Unspecified elements will be set to zero automatically. • Array declarations may omit the size. int counter[] = {1, 1, 1, 1}; char RGB_image[][3] = { {255,0,255}, {0,255,0}}; • Problems with C initialization of arrays • No convenient way to initialize selected elements. • No shortcut to initialize large number of elements.
Local Array Example Arrays SP int main() { int array[10]; int x; for (x = 0; x < 10; x++) { array[x] = x; } return 0; } main: 0x8040: 8031 0016 SUB.W #0x0016,SP 0x8044: 4381 0014 CLR.W 0x0014(SP) 0x8048: 90B1 000A 0014 CMP.W #0x000a,0x0014(SP) 0x804e: 340D JGE (C$DW$L$main$2$E) C$DW$L$main$2$B, C$L1: 0x8050: 411F 0014 MOV.W 0x0014(SP),R15 0x8054: 5F0F RLA.W R15 0x8056: 510F ADD.W SP,R15 0x8058: 419F 0014 0000 MOV.W 0x0014(SP),0x0000(R15) 0x805e: 5391 0014 INC.W 0x0014(SP) 0x8062: 90B1 000A 0014 CMP.W #0x000a,0x0014(SP) 0x8068: 3BF3 JL (C$L1) C$L2, C$DW$L$main$2$E: 0x806a: 430C CLR.W R12 0x806c: 5031 0016 ADD.W #0x0016,SP 0x8070: 4130 RET C_Arrays.c
Global Array Example Arrays int array[10]; int x; int main() { for (x = 0; x < 10; x++) { array[x] = x; } return 0; } main: 0x806a: 4382 0214 CLR.W &x 0x806e: 90B2 000A 0214 CMP.W #0x000a,&x 0x8074: 340C JGE (C$DW$L$main$2$E) C$DW$L$main$2$B, C$L1: 0x8076: 421F 0214 MOV.W &x,R15 0x807a: 5F0F RLA.W R15 0x807c: 429F 0214 0200 MOV.W &x,0x0200(R15) 0x8082: 5392 0214 INC.W &x 0x8086: 90B2 000A 0214 CMP.W #0x000a,&x 0x808c: 3BF4 JL (C$L1) C$L2, C$DW$L$main$2$E: 0x808e: 430C CLR.W R12 0x8090: 4130 RET
C Strings C Strings • A C string is an array of characters: • char outputString[16]; • C strings are terminated with a zero byte. • C strings can be initialized when defined: char outputString[] = "Text"; which is the same as: outputString[0] = 'T'; outputString[1] = 'e'; outputString[2] = 'x'; outputString[3] = 't'; outputString[4] = 0; • C has no string operators. • String functions in <string.h> library • strcpy, strlen, strcmp, strstr, … Compiler computes the size of the array (4 + 1 = 5 bytes)
Arrays Common Pitfalls with Arrays • Overrun array limits. • There is no boundary checking in C. int array[10], i; for (i = 0; i< 100; i++) // oops array[i] = 0; • Arrays must be statically declared • Compiler flags run-time declarations void SomeFunction(intnum_elements) {int temp[num_elements]; // error … }
Array Arguments Passing Arrays as Arguments • C passes parameters to functions by value. • C passes the address of the 1st element of an array. #define MAX_NUMS 5 int average(int values[]) { inti, sum = 0; for (i = 0; i < MAX_NUMS; i++) sum = sum + values[i]; return (sum / MAX_NUMS); } int main() { intnums[MAX_NUMS] = { 1, 2, 3, 4, 5 }; int mean = average(nums); return 0; } 0x05f2 SP 5 15 1 SP 2 3 4 5 3
Pointers K&R Ch.5
Pointers Swap Function Example int main() { int a = 3; int b = 4; swap(a, b); } void swap(int a, int b) { int temp = a; a = b; b = temp; } Stack after call to swap(): 4 a 3 b swap temp 3 Return Adr main
Pointers Pointers int* ptr; • char* cp; • double* dp; • int** p_ptr = &ptr; • char *strings[10]; • A pointer is an address • With pointers • functions can indirectly access variables. • functions can modify the arguments passed by the caller function. • sophisticated data structures can grow and shrink at run-time. • Arrays and pointers are closely related. • Array pointers enable us to conveniently process groups of data such as vectors, lists, and strings. • A pointer variable contains a memory address • Associated with a pointer variable is the type of value to which it points. • The asterisk (*) indicates that the following identifier is a pointer variable. • The ampersand (&) returns a pointer (address) to the following identifier.
Pointers Pointer Operators • A pointer variable is declared with the asterisk operator (*) type *var; // same - whitespace doesn’t matter type* var; • Dereferencing any expression returns a value *varreturns contents of the memory location pointed to by var **varreturns contents of the memory location pointed to by the memory location pointed to by var *3 returns the contents of memory location 3 • A pointer is created with the reference operator (&) &var • Reference must be applied to a memory object • &3 is illegal as it would return a pointer to a constant
* =dereference & = reference Pointers Operator Precedence and Associativity
0x05fa 0x05fc Pointers Examples of Pointers int *ptr1; int *ptr2; inti = 4; int j; ptr1 = &i; ptr2 = &j; // What will these print? print(ptr1); print(ptr2); print(*ptr1); print(*ptr2); j = *ptr1; print(j); 4 4 0x05fa 0x05fc 0x0004 ?????? 0x0004
3 4 Swap Example w/Pointers Swap Example Fixed! • Stack after call to swap() int main() { int a = 3; int b = 4; swap(&a, &b); } void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } 0x05fa a 0x05fc b swap temp 3 Return Adr main C_Pointers.c
Pointer Arithmetic Pointer Arithmetic • Address calculations depend on size of elements • ints are 16-bits or 2 bytes per element. • e.g., to find 4th element (x[3]), we add 3*2 to base address • If double, we'd have to add 12 (3*4) to find address of 4th element. • C does size calculations under the covers,depending on size of item being pointed to: double x[10]; double *y = x; *(y + 3) = 13; y++; *y = 3.1415926; Allocates 40 bytes (4 per element) Same as x[3] (base address plus 12) x[1] = 3.1415926
2 5 2 3 6 // y = a[0]+1 y=2, ip=0x05f2 // a[0] = a[0]+1 y=2, ip=0x05f2 0x05f4 // y = ++a[0] y=3, ip=0x05f2 // y = a[0], ip++ y=3, ip=0x05f4 // y=a[1], a[1]++ y=5, ip=0x05f4 Pointer Arithmetic Incrementing Pointers • A pointer increments according to its type. • The unary operators * and & bind more tightly than arithmetic operators. 0 3 int y = 0; int a[5] = {1, 5, 9, 13, 17}; int* ip = &a[0]; y = *ip + 1; *ip += 1; y = ++*ip; y = *ip++; y = (*ip)++; 1 5 9 13 17 0x05f2
Pointer Arithmetic *ip++ • Alternate forms of pointer arithmetic // strcpy: copy s to d; version 1 void strcpy(char* d, char* s) { while ((*d = *s) != ‘\0’) { d++; s++; } } // strcpy: copy s to d; version 2 void strcpy(char* d, char* s) { while ((*d++ = *s++) != ‘\0’); } • The value of *s++ is the character that s pointed to before s was incremented; the postfix ++ does not change s until after this character has been fetched.
Example // #include "msp430.h" void main(void) { char dog[] = {1, 2, 3, 4, 5, 6}; intcat[] = {1, 2, 3, 4, 5, 6); long pig[] = {1, 2, 3, 4, 5, 6); char* apple = dog; int* orange = cat; long* banana = pig; lcd_init(); // initlcd printLcd(*(++apple + 2)); printLcd(&orange[5] - cat); printLcd((int)&orange[5] - (int)cat); printLcd((pig + 2) - banana); printLcd((int)(pig + 2) - (int)&banana[0]); } 1. What is output?
h e l l o \0 a: w o r l d \0 p: Arrays and Pointers • Array names are NOT pointer variables • char a[6]; • Requests memory for 6 characters, to be known by the name “a”. • “a” is not a variable and known only at compile time (ie. defined in the compiler symbol table). • char *p; • Requests memory for a single pointer variable, to be known by the name “p”. • “p” can point to any char (or contiguous array of chars). • Example: char a[] = "hello"; char *p = "world";
Arrays and Pointers Arrays and Pointers • An array name (at compile time) is essentially a pointer to the first element in an array. • Can change the value (contents) of a pointer. char word[10]; char *cptr; cptr = word; // points to word[0] • Each of the following lines evaluate the same: cptr word &word[0] address of word[0] (cptr + n) (word + n) &word[n] address of word[n] *cptr *word word[0] value of word[0] *(cptr + n) *(word + n) word[n] value of word[n]
Static Variables Static Variables • Static variables are “global local” variables • May be declared inside a C function • Like local variables, a static variable cannot be referred to outside the function • However, unlike a local variable, the value continues to exist even after the function exits • The value comes back into scope when the function is called again (value retained) • A function can pass out a point to a static variable and de-reference the value static int sum = 0;
Static Variables Static Array • Pointer to static array // month_name: return name of n-th month char* month_name(int n) { static char* name[ ] = { "Illegal month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; return ( n < 1 || n > 12 ) ? name[0] : name[n]; } // end month_name
Example • Show different ways to access the character 'o' in the array x without using brackets. char x[] = "Hello"; char* y = x; char** z = &y; Want x[4]: *(x+4) *(y+4) Z[0][4] *(z[0]+4) *(*z+4) *(*(&y)+4)
Parsing String Parsing • What is the value of X? char str[] = "Point X = 100"; Walk the array until token or NULL terminator. (Token must be unique) • Find token: char* ptr = str; int number = 0; while (*ptr && (*ptr++ != 'X')); • Find beginning of number: while (*ptr && !isdigit(*ptr)) ++ptr; • Convert to decimal: while (isdigit(*ptr)) number = number * 10 + (*ptr++ - '0'); isdigit returns 0 or 1 • Proceed with parsing of line. Return result in number
C I/O Formatted Input/Output • The printf function outputs formatted values to the stdout stream using putc printf( const char *format, ... ); printf("\nX = %d, Y = %d", x, y); Output y as an ASCII string • The function scanf is similar to printf, providing many of the same conversion facilities in the opposite direction: scanf( const char *format, ... ); scanf("%s = %f", name, &cost); name and cost MUST be pointers • Decimal "%d" or "%i" • String "%s" • Character "%c“ • Hexadecimal "%x“ • Unsigned decimal "%u • Floating point "%f" • Scientific notation "%e" • Pointer "%p" • % "%%"
linesptr[0] defghi linesptr[1] lmnopqrstuvwxyz linesptr[2] abc … Pointers to Pointers Pointers to Pointers • Since pointers are variables themselves, they can be stored in arrays just as other variables can. Example: char* lines[8]; char** linesptr = lines; char* lines[8]; //char** linesptr = &lines[0]; //char** linesptr = &*lines; char** linesptr = lines; linesptr[0][0] = 'c';
linesptr[0] linesptr[1] linesptr[2] … Pointers to Pointers Pointers to Pointers • Since pointers are variables themselves, they can be stored in arrays just as other variables can. Example: char* lines[8]; char** linesptr = lines; defghi lmnopqrstuvwxyz abc
Multi-dimensional Arrays Multi-dimensional Arrays • Multi-dimensional arrays declared with multiple indexes • Pointers to pointers… • daytab[i][j] /* [row][col] */ • daytab[i,j] /* WRONG! */ • Array elements are stored by rows • The rightmost subscript varies the fastest • Array name “points” to 1st element • Multi-dimensional arrays passed to a function • by value (address of 1st element in 1st row, 1st column… • must declare the number of elements for every subscript except the first • func(intdaytab[ ][13]) {…}
These are OK main Function The main Function Return code for system # of command line arguments • The main function • must be present in every C program. • is “called” by the operating system. • exits the program with a return statement. • The prototype of main is pre-declared as: int main (intargc, char *argv[]); • The definition doesn’t have to match. int main() { ... }main() { ... } • The return statement can be omitted.
C main to Assembly main Function main: 0x8040: 8031 000A SUB.W #0x000a,SP 0x8044: 4D81 0002 MOV.W R13,0x0002(SP) 0x8048: 4C81 0000 MOV.W R12,0x0000(SP) 0x804c: 40B1 0007 0004 MOV.W #0x0007,0x0004(SP) 0x8052: 40B1 0005 0006 MOV.W #0x0005,0x0006(SP) 0x8058: 411C 0004 MOV.W 0x0004(SP),R12 0x805c: 411D 0006 MOV.W 0x0006(SP),R13 0x8060: 12B0 80DA CALL #__mpyi 0x8064: 4C81 0008 MOV.W R12,0x0008(SP) 0x8068: 430C CLR.W R12 0x806a: 5031 000A ADD.W #0x000a,SP 0x806e: 4130 RET __mpyi: 0x80da: 430E CLR.W R14 mpyi_add_loop: 0x80dc: C312 CLRC 0x80de: 100C RRC R12 0x80e0: 2801 JLO shift_test_mpyi 0x80e2: 5D0E ADD.W R13,R14 shift_test_mpyi: 0x80e4: 5D0D RLA.W R13 0x80e6: 930C TST.W R12 0x80e8: 23F9 JNE mpyi_add_loop 0x80ea: 4E0C MOV.W R14,R12 0x80ec: 4130 RET int main(intargc, char** argv) { unsigned int x = 7; unsigned int y = 5; unsigned int z; z = x * y; return 0; } x05f4 SP argc (r12) x05f6 argv (r13) x05f8 x x05fa y x05fc z x05fe ret adr x0600 Stack
Example char* constmenuText[] = { "MSPEXP430F5438", " 1. App1", " 2. App2", " 3. App3", " 4. App4", " 5. App5", " 6. App6", " 7. App7", }; // menuText[0] = addr of "MSP...", *menuText[0]='M'.