330 likes | 642 Views
Array. Outline. Nested array Memory layout for array Static vs. dynamic Compiler optimization for array operations Suggested reading 3.8.3, 3.8.4, 3.8.5. Nested Array. int A[4][3] ; Array A is a two-dimensional array with four rows and three columns
E N D
Outline • Nested array • Memory layout for array • Static vs. dynamic • Compiler optimization for array operations • Suggested reading • 3.8.3, 3.8.4, 3.8.5
Nested Array • int A[4][3] ; • Array A is a two-dimensional array • with four rows and three columns • It is referenced as A[0][0] through A[3][2]
Nested Array • int A[4][3] ; • Array of array • typedef int row3_t[3] ; • row3_t A[4] ; • Array A contains 4 elements, each requiring 12 bytes to store 3 integers • The whole size of array A is 48 bytes • Row major ordered in memory
Nested Array • T D[R][C] ; • D[i][j] is at memory address • xD + L * ( C * i + j ) • L is sizeof(T)
Access A[i,j] • It is in memory M [ xA + j*4 + i*12 ] %eax contains xA %edx holds i, %ecx holds j sall $2, %ecx # j*4 leal (%edx, %edx, 2), %edx # i*3 leal (%ecx, %edx, 4), %ecx # j*4+ i*12 movl (%eax, %ecx), %eax
Fixed-size Arrays #define N 16 typedef int fix_matrix[N][N]; /* Compute i,k of fixed matrix product */ int fix_prod_ele (fix_matrix A, fix_matrix B, int i, int k) { int j; int result = 0; for (j = 0; j < N; j++) result += A[i][j] * B[j][k]; return result; }
Observations • The loop will access the elements of array A • as A[i][0], A[i][1], …, A[i][15] in sequence • These elements occupy adjacent positions in memory • starting with the address of array A[i][0] • Use a pointer variable Arow • to access these successive locations.
Observations • The loop will access the elements of array B • as B[0][k], B[1][k], …, B[15][k] in sequence • These elements occupy positions in memory • starting with the address of array B[0][i] • and space 64 bytes apart. • Use a pointer variable Bptr • to access these locations. • Use a simple counter • to keep track of the number of iterations required
Fixed-size Arrays /* Compute i,k of fixed matrix product */ int fix_prod_ele_opt (fix_matrix A, fix_matrix B, int i, int k) { int *Arow = &A[i][0], *Bptr = &B[0][k]; int j, result = 0; for ( j = 0; j < 16; j++) { result += Arow[j] * (*Bptr); Bptr += N; } return result; }
Fixed-size Arrays Arow in %esi, Bptr in %ecx result in %ebx, j in %edx .L6: #loop: movl (%ecx),%eax # Get *Bptr imull (%esi, %edx, 4),%eax # Multiply by Arow[j] addl %eax,%ebx # Add to result addl $1, %edx # j++ addl $64,%ecx # Add 16*4 to Bptr cmpl $16,%edx # compare j : 16 jne .L6 # if !=, goto loop
Variable-Size Arrays int var_ele(int n, int A[n][n], int i, int j) { return A[i][j]; } • Declare an array int A[exp1][exp2] • either as a local variable • or as an argument to a function • The dimensions of the array are determined • by evaluating the expressions at the time the declaration is encounterd
Assembly Code n at %ebp+8, A at %ebp+12 i at %ebp+16, j at %ebp+20 movl 8(%ebp), %eax # Get n sall $2, %eax # Compute 4*n movl %eax, %edx # Copy 4*n imull 16(%ebp), %edx # Compute 4*n*i movl 20(%ebp), %eax # Get j sall $2, %eax # Compute 4*j addl 12(%ebp), %eax # Compute xA+ 4∗j movl (%eax,%edx), %eax # Read from xA + 4∗(n∗i + j)
Optimization /* Compute i,k of variable matrix product */ int var_prod_ele (int n, int A[n][n], int B[n][n], int i, int k) { int j; int result = 0; for (j = 0; j < n; j++) result += A[i][j] * B[j][k]; return result; }
Assembly Code n stored at %ebp+8 Registers: Arow in %esi, Bptr in %ecx, j in %edx, result in %ebx, %edi holds 4*n .L30: #loop: movl (%ecx), %eax # Get *Bptr imull (%esi,%edx,4), %eax # Multiply by Arow[j] addl %eax, %ebx # Add to result addl $1, %edx # Increment j addl %edi, %ecx # Add 4*n to Bptr cmpl %edx, 8(%ebp) # Compare n:j jg .L30 # If >, goto loop 8(%ebp) Register spill
Outline • Understanding Pointers • Suggested reading • Chap 3.10
Pointers • Every pointer has a type • If the object has type T • A pointer to this object has type T * • Special void * type • Represents a generic pointer • malloc returns a generic pointer • Every pointer has a value
Pointers • Pointers are created with the & operator • Applied to lvalue expression • Lvalue expression can appear on the left side of assignment • Pointers are dereferenced with the operator * • The result is a value having the type associated with the pointer • Arrays and pointers are closed related • The name of array can be viewed as a pointer constant • ip[0] is equivalent to *ip
Pointer Arithmetic • Addition and subtraction • p+i , p-i (result is a pointer) • p-q (result is a int) • Referencing & dereferencing • *p, &E • Subscription • A[i], *(A+i)
Example static char daytab[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} } /* day_of_year: set day of year from month & day */ int day_of_year(int year, int month, int day) { int i, leap; leap = (year%4 == 0 && year%100 != 0 && year%400 ==0); for(i = 1; i < month; i++) day += daytab[leap][i]; returnday; }
Example /* month_day: set month, day from day of year */ int month_day(int year, int yearday, int *pmonth, int *pday) { inti, leap; leap = (year%4 == 0 && year%100 != 0 && year%400 ==0); for (i = 1; yearday > daytab[leap][i] ; i++) yearday -= daytab[leap][i]; *pmonth = i; *pday = yearday; }
Pointer Array /* month_name: return name of n-th month */ int 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]; }
Pointer Array Illegal month\0 January\0 February\0 March\0 April\0 May\0 June\0 July\0 August\0 September\0 October\0 November\0 December\0
Command-line Arguments $echo hello, world $hello, world #include <stdio.h> /* echo command-line arguments */ int main(int argc, char *argv[]) { int i ; for (i = 1; i < argc ; i++) printf(“%s%s”, argv[i], (i < argc-1) ? “ ” : “”); printf(“\n”) ; return 0; } argv: echo\0 Hello,\0 World\0
Command-line Arguments #include <stdio.h> /* echo command-line arguments ; 2nd version*/ int main(int argc, char *argv[]) { while(--argc > 0) printf(“%s%s”, ++argv, (argc > 1) ? “ ” : “”); printf(“\n”); return0; } or printf((argc > 1) ? “%s ” : “%s”, ++argv);
Pointer to Function #include <stdlib.h> /* numcmp: compare s1 and s2 numerically */ int numcmp(char *s1, char *s2) { doublev1, v2; v1 = atof(s1); v2 = atof(s2); if (v1 < v2) return -1; else if ( v1 > v2 ) return1; else return0; }
Pointer to Function #include <stdio.h> #include <string.h> { ... int numeric = 0, (*cmp)(void *, void *); char *s1, *s2; ... if(...) numeric = 1 ; ... cmp = (int (*)(void *, void *)) (numeric ? numcmp: strcmp); (*cmp)(s1, s2); ... }
Pointers can point to functions • void (*f)(int *) • f is a pointer to function • The function taken int * as argument • The return type of the function is void • Assignment makes f point to func • f = func • Notice the precedence of the operators • void *f(int *) declares f is a function • (void *) f(int *)
Pointer Declaration • char **argv ; • int (*daytab)[13] • int (*comp)() • char (*(*x())[])() • Function returning pointer to array[ ] of pointer to function returning char • char (*(*x[3])())[5] • Array[3] of pointer to function returning pointer to array[5] of char
C operators Operators Associativity () [] -> . ++ -- left to right ! ~ ++ -- + - * & (type) sizeof right to left * / % left to right + - left to right << >> left to right < <= > >= left to right == != left to right & left to right ^ left to right | left to right && left to right || left to right ?: right to left = += -= *= /= %= &= ^= != <<= >>= right to left , left to right Note: Unary +, -, and * have higher precedence than binary forms
Parameter Passing • Call by value • f(xp) • Call by reference • f(&xp)