COMP 21000 Introduction to Computer Organization Systems Chap

  • Slides: 44
Download presentation
COMP 21000 Introduction to Computer Organization & Systems Chap 2. 2 Topics: n C

COMP 21000 Introduction to Computer Organization & Systems Chap 2. 2 Topics: n C pointers n Pointers to arrays

Pointers • Why learn pointers? – pointers are necessary for dynamic memory – dynamic

Pointers • Why learn pointers? – pointers are necessary for dynamic memory – dynamic memory is necessary for efficiency – even with static memory, pointers are theoretically more efficient • actually, compilers do a great job weeding out inefficiencies • even if you run a compiler without optimization it will generate code for array syntax that is the same as code for pointer syntax – helps us to understand how the hardware (memory) works 2 -2

Pointers #include <stdio. h> Pointer declaration int main() { int n 1, n 2,

Pointers #include <stdio. h> Pointer declaration int main() { int n 1, n 2, *int. Ptr; Pointer assignment int. Ptr = &n 1; printf ( "Enter two numbersn"); scanf("%d%d", &n 1, &n 2); printf ( "The numbers you entered are: %d and %d n", n 1, n 2); printf ("n 1 is %dn", *int. Ptr); int. Ptr = &n 2; Accessing value that pointer points at printf ( "n 2 is %dn", *int. Ptr); *int. Ptr = n 1 + n 2; printf ( "and their sum is: %dn”, *int. Ptr); } Changing a value in variable that pointer points at See Student/examples/pointers/ptr 1. c 2 -3

dynamic memory • Two types of memory: static and dynamic • Static – allocated

dynamic memory • Two types of memory: static and dynamic • Static – allocated to your program when it is loaded – never changes • dynamic – requested by your program when needed – comes and goes as your program runs 2 -4

dynamic memory • Consider MS Word – a very large program – must store

dynamic memory • Consider MS Word – a very large program – must store the words in a document in memory – how much memory do you allocate? How do you know? 2 -5

Dynamic Memory Example #include <stdio. h> #include <stdlib. h>›//need this library int main() {

Dynamic Memory Example #include <stdio. h> #include <stdlib. h>›//need this library int main() { int *int. Ptr; // int. Ptr is a pointer to an int int. Size = sizeof(int); int. Ptr = (int *)malloc(int. Size); // must first allocate memory printf("Enter an integer: "); scanf("%d", int. Ptr); printf("You entered %dn", *int. Ptr); // why no & in front of int. Ptr? return 0; } See Student/comp 210/examples/pointers/ptr 2. c 2 -6

Pointers & dynamic memory sizeof is a library function that returns the number of

Pointers & dynamic memory sizeof is a library function that returns the number of bytes in the data type given as an arg #include <stdio. h> int main() (int *)malloc(num. Of. Bytes); { int n 1, n 2, *int. Ptr; int num. Of. Bytes = sizeof(int); malloc returns (void *) by default; int. Ptr = (int *)malloc(num. Of. Bytes); we must cast to an (int *) printf ( "Enter two numbersn"); argument is the number scanf("%d%d", &n 1, &n 2); of bytes to allocate. printf ( "The numbers you entered are: %d and %d n", n 1, n 2); *int. Ptr = n 1 + n 2; printf ( "and their sum is: %dn”, *int. Ptr); free(int. Ptr); return 0; } Must always free dynamically allocated memory! See Student/comp 210/examples/pointers/ptr 3. c 2 -7

Arrays (review) // ex 2. c int main() { int line[SIZE]; int i, n;

Arrays (review) // ex 2. c int main() { int line[SIZE]; int i, n; You do have to specify the size of an array that is a variable (unless you want to use dynamic memory) n = readints(line, SIZE); printf("The numbers you entered are: n"); for (i = 0; i < n; i++) { printf("%dn", line[i]); } } 2 -8

Arrays (review) // ex 2. c #include <stdio. h> #define SIZE 5 You don’t

Arrays (review) // ex 2. c #include <stdio. h> #define SIZE 5 You don’t have to specify the size of an array that is a parameter int readints(int s[ ], int max) { int c, i=0; printf("Enter %d numbers: n", max); while (i < max) scanf("%d", &s[i++]); return(i); } 2 -9

Pointer Arithmetic • Incrementing a pointer causes it to be changed by the appropriate

Pointer Arithmetic • Incrementing a pointer causes it to be changed by the appropriate number of memory locations int *int. Ptr; int arr[10]; int. Ptr = arr; • int. Ptr points at arr[0] int. Ptr++; // or int. Ptr = int. Ptr + 1; • int. Ptr now points at arr[1] 2 -10

Pointer Arithmetic #include <stdio. h> #define SIZE 5 int main() { int *int. Ptr;

Pointer Arithmetic #include <stdio. h> #define SIZE 5 int main() { int *int. Ptr; int i, arr[SIZE]; int. Ptr = arr; for(i = 0; i < SIZE; i++) { arr[i] = i * 11; } printf ( "arr[0] = %dn", *int. Ptr); printf ( "int. Ptr = %pn", int. Ptr); int. Ptr++; printf ( "arr[1] = %dn", *int. Ptr); printf ( "int. Ptr = %pn", int. Ptr); return 0; } %p means print a pointer 2 -11 * This example is on the server at /home/barr/Student/comp 210/examples/pointer_arith. c

Arrays and Pointers int main() { int line[SIZE]; we’re still allocating the array statically…

Arrays and Pointers int main() { int line[SIZE]; we’re still allocating the array statically… int i, n, *int. Ptr; int. Ptr = line; remember that array names are pointers! n = readints(line, SIZE); printf("The numbers you entered are: n"); for (i = 0; i < n; i++) { printf("%dn", (*int. Ptr)++ ); } …but we’re using pointer arithmetic to access an array } * This example is on the server at /home/barr/Student/comp 210/examples/pointers/array_ptr 1. c Compile this into a. out with the command: gcc array_ptr 1. c readints. c 2 -12

Arrays and Pointers for (i = 0; i < n; i++) assume that n

Arrays and Pointers for (i = 0; i < n; i++) assume that n is 5 { printf("%dn", *(int. Ptr++)); } remember pointer arithmetic! int. Ptrint. Ptr index 0 1 2 3 4 value 111 222 333 444 555 2 -13

Arrays and Pointers #include <stdio. h> #define SIZE 5 An array is a pointer

Arrays and Pointers #include <stdio. h> #define SIZE 5 An array is a pointer and vice versa int readints(int *s, int max) { int c, i=0; printf("Enter %d numbers: n", max); while (i < max){ scanf("%d", s++); i++; notice that there’s no ‘&’ before s. Why? } return(i); } 2 -14

Arrays and Pointers notice that there’s no ‘&’ before s. Why? while (i <

Arrays and Pointers notice that there’s no ‘&’ before s. Why? while (i < max){ scanf("%d", s++); i++; } s s 1 s s s 2 3 4 index 0 value 111 222 333 444 555 2 -15

Arrays and Pointers • Note that this is valid syntax: #include <stdio. h> int

Arrays and Pointers • Note that this is valid syntax: #include <stdio. h> int main() { int arr[10]; } Try it! 5[arr] = 11; printf("arr[5] = %dn", arr[5]); 2 -16

Passing Arrays & dynamic memory #include <stdlib. h> #include <stdio. h> malloc returns a

Passing Arrays & dynamic memory #include <stdlib. h> #include <stdio. h> malloc returns a (void *), so it must be cast. int main() { int *line; must determine int i, n, *int. Ptr, the. Size; how much storage printf("Enter the size of the arrayn"); we need scanf("%d", &the. Size); line = (int *) malloc(the. Size * sizeof(int)); int. Ptr = line; n = readints(line, the. Size); printf( "The numbers you entered are: n"); Using pointer arithmetic to access an array for (i = 0; i < n; i++) { printf("%dn", *int. Ptr++); } free(line); // always dynamically allocated storage Note thatfree memory that is allocated must be freed! } * This example is on the server at /home/barr/Student/comp 210/examples/array_pass_ptr. c Compile this into a. out with the command: gcc array_pass. c readints. c 2 -17

Arrays and Pointers dynamic memory #include <stdio. h> An array is a pointer and

Arrays and Pointers dynamic memory #include <stdio. h> An array is a pointer and vice versa int readints(int *s, int max) { int c, i=0; printf("Enter %d numbers: n", max); while (i < max) scanf("%d", &s[i++]); return(i); } 2 -18

Returning Arrays* // array_return. c #include <stdio. h> // needed for malloc #include <stdlib.

Returning Arrays* // array_return. c #include <stdio. h> // needed for malloc #include <stdlib. h> #define SIZE 5 Compile this into a. out with the command: gcc array_return. c readints 2. c must have a function prototype if you’re going to define the function after main( ) int *readints 2(int max); int main() { int i; int *line; readints will return a pointer to a new array To receive an array, just use the pointer variable name line = readints(SIZE); printf("The numbers you entered are: n"); for (i = 0; i < SIZE; i++) { printf("%dn", *(line + i)); } } notice the pointer arithmetic. * This example is on the server at /home/barr/Student/comp 210/examples/array_return. c 2 -19

Returning Arrays Must return a pointer to an int* readints 2(int max) { int

Returning Arrays Must return a pointer to an int* readints 2(int max) { int c, i=0; int *new. Array; Must use a pointer variable Must allocate memory new. Array = (int *)malloc(sizeof(int)*SIZE); printf("Enter %d numbers: n", max); while (i < max) { scanf("%d", &new. Array[i++]); Return the pointer } return(new. Array); } * This example is on the server at /home/barr/Student/comp 210/examples/readints 2. c 2 -20

Strings #include <stdio. h> int lower(int c) { if (c >= 'A' && c

Strings #include <stdio. h> int lower(int c) { if (c >= 'A' && c <= 'Z') return(c + 'a' - 'A'); else return(c); } int main() { int c; printf("Enter some characters. To end input hit ^D on a new linen"); /* read char until end of file */ while ( (c = getchar()) != EOF) putchar(lower(c)); } 2 -21

Strings as arrays #include <stdio. h> int strequal(char x[ ], char y[ ]) {

Strings as arrays #include <stdio. h> int strequal(char x[ ], char y[ ]) { int i=0; if (x == y) return(1); while (x[i] == y [i]) { if (x[i] == '') return (1); i++; } return(0); } 2 -22

Strings as arrays #include <stdio. h> #include <stdio_ext. h> int main() { char str

Strings as arrays #include <stdio. h> #include <stdio_ext. h> int main() { char str 1[10], str 2[10]; printf("Enter a stringn"); scanf("%s", str 1); __fpurge(stdin); printf("n. Enter another stringn"); scanf("%s", str 2); if (strequal(str 1, str 2)) printf("The strings are equaln"); else printf("The strings are not equaln"); } 2 -23

Strings and Pointers #include <stdio. h> #include <ctype. h> int main() { char alpha[

Strings and Pointers #include <stdio. h> #include <ctype. h> int main() { char alpha[ ] = "abcdefghijklmnopqrstuvwxyz"; char *str_ptr; An array name is a pointer str_ptr = alpha; Strings always end with the ‘’ character while(*str_ptr != '') printf ("%c ", toupper(*str_ptr++) ); printf("n"); } “toupper” is a function defined in the ctype. h library. 2 -24

Strings: readline #include <stdio. h> #define SIZE 100 int readline(char s[ ], int max)

Strings: readline #include <stdio. h> #define SIZE 100 int readline(char s[ ], int max) { int c, i=0; max--; while (i < max && (c = getchar()) != EOF && c != 'n') s[i++] =c; if (c == 'n') s[i++] = c; s[i] = ''; return(i); } 2 -25

Strings: readline int main() { char line[SIZE]; int n; while ( (n = readline(line,

Strings: readline int main() { char line[SIZE]; int n; while ( (n = readline(line, SIZE) ) > 0) printf("n = %d t line = %sn", n, line); } 2 -26

Strings and dynamic memory #include <string. h> /* compare two strings character by character

Strings and dynamic memory #include <string. h> /* compare two strings character by character using array syntax */ int strequal(char x[ ], char y[ ]) { int i=0; if (x == y) return(1); while (x[i] == y [i]) { if (x[i] == '') return (1); i++; } return(0); } 2 -27

Strings and dynamic memory int main() { char *str 1, *str 2; str 1

Strings and dynamic memory int main() { char *str 1, *str 2; str 1 = (char *) malloc(20 * sizeof(char)); str 2 = (char *) malloc(20 * sizeof(char)); Strcmp is a library function printf("Enter a string or ! to halt n"); scanf("%s", str 1); while (strcmp(str 1, "!") != 0){ strequal is a user defined function printf("n. Enter another stringn"); scanf("%s", str 2); if (strequal(str 1, str 2)) printf("The strings are equaln"); else printf("The strings are not equaln"); printf("Enter a string or ! to halt n"); scanf("%s", str 1); } } 2 -28

Strings and pointers int strequal(char *x, char *y) ; // function prototype #define DEBUG

Strings and pointers int strequal(char *x, char *y) ; // function prototype #define DEBUG 1 int main() Use #define to put in debug statements { char *str 1, *str 2; str 1 = (char *) malloc(10 * sizeof(char)); str 2 = (char *) malloc(10 * sizeof(char)); If then"); name DEBUG is #defined, then printf("Enter a string or ! to halt #ifdef is true and the printf is included. scanf("%s", str 1); #ifdef DEBUG printf("This is a debug statement. str 1 is %s n", str 1); #endif while (strcmp(str 1, "!") != 0){ printf("n. Enter another stringn"); scanf("%s", str 2); if (strequal(str 1, str 2)) printf("The strings are equaln"); else printf("The strings are not equaln"); printf("Enter a string or ! to halt n"); scanf("%s", str 1); } } See Student/comp 210/examples/strings/str_dynam. c 2 -29

Strings and pointers #include <stdio. h> #include <string. h> *x is the contents of

Strings and pointers #include <stdio. h> #include <string. h> *x is the contents of what x points at int strequal(char *x, char *y) { if (x == y) return(1); while (*x++ == *y++) { if (*x == '' && *y == '') return (1); } return(0); } Return true if at end of string 2 -30

Structs and Pointers #include <stdio. h> #include <stdlib. h> #include <stdio_ext. h> #define MAX

Structs and Pointers #include <stdio. h> #include <stdlib. h> #include <stdio_ext. h> #define MAX 3 struct person{ char name[32]; int id; }; int main() { struct person *students; struct person *std. Ptr; int i; FILE *s. File; char file. Name[50]; 2 -31

Structs and Pointers students = (struct person*)malloc(MAX * sizeof(struct person)); std. Ptr = students;

Structs and Pointers students = (struct person*)malloc(MAX * sizeof(struct person)); std. Ptr = students; for (i = 0; i < MAX; i++) { printf("Enter name: "); scanf(“%s”, std. Ptr->name); // or (*std. Ptr). name printf("Enter id: "); scanf("%d", &std. Ptr->id); // or &((*std. Ptr). id)) __fpurge(stdin); std. Ptr++; } 2 -32

Printing/writing to file printf("n. Students: n"); std. Ptr = students; for (i = 0;

Printing/writing to file printf("n. Students: n"); std. Ptr = students; for (i = 0; i < MAX; i++) { printf("%s", std. Ptr->name); printf(", %dn", std. Ptr->id); std. Ptr++; } printf("Enter name of file to write students to: "); __fpurge(stdin); scanf("%s", file. Name); s. File = fopen(file. Name, "w"); if (s. File == NULL){ fprintf(stderr, "failed to open %sn", file. Name); } 2 -33

Writing to file else{ printf("writing to %sn", file. Name); std. Ptr = students; for

Writing to file else{ printf("writing to %sn", file. Name); std. Ptr = students; for (i = 0; i < MAX; i++){ fprintf(s. File, "%sn", std. Ptr->name); fprintf(s. File, "%dn", std. Ptr->id); std. Ptr++; } } } 2 -34

Writing Structs as bytes Size of struct that you’re writing // “wb" means ”write

Writing Structs as bytes Size of struct that you’re writing // “wb" means ”write bytes” s. File = fopen("students. txt", "wb"); int num. Written = fwrite(students, sizeof(struct person), 10, s. File); printf("Wrote %d elementsn", num. Written); fwrites bytes and returns the number of bytes written Pointer to memory from which to write, e. g. , an array of struct File pointer Number of elements that you’re writing fwrite reference: https: //www. tutorialspoint. com/c_standard_library/c_function_fwrite. htm 2 -35

Reading Structs as bytes Size of struct that you’re reading // "rb" means "read

Reading Structs as bytes Size of struct that you’re reading // "rb" means "read bytes" s. File = fopen("students. txt", "rb"); int num. Read = fread(students, sizeof(struct person), 5, s. File); printf("Read %d elementsn", num. Read); fread returns the number of elements read Pointer to memory to read into, e. g. , an array of struct File pointer Number of elements to read fread reference: https: //www. tutorialspoint. com/c_standard_library/c_function_fread. htm 2 -36

initializing memory • loops are slow • array access is slow • better to

initializing memory • loops are slow • array access is slow • better to deal with memory directly: memset 2 -37

buffer manipulation Function Description memset() It is used to initialize a specified number of

buffer manipulation Function Description memset() It is used to initialize a specified number of bytes to null or any other value in the buffer memcpy() It is used to copy a specified number of bytes from one memory to another memmov() It is used to copy a specified number of bytes from one memory to another or to overlap on same memory. Difference between memmove and memcpy is, overlap can happen on memmove whereas memcpy should be done in non-destructive way memcmp() It is used to compare specified number of characters from two buffers memicmp() It is used to compare specified number of characters from two buffers regardless of the case of the characters memchr() It is used to locate the first occurrence of the character in the specified string 2 -38

buffer set int main() { int i; /* allocate memory for array of 5

buffer set int main() { int i; /* allocate memory for array of 5 elements */ char *a = (char *) malloc(5*sizeof(char)); /* All elements are set to c. It can be set to any value */ memset(a, ‘c’, 5*sizeof(char)); memset sets bytes. The second arg must be printf("n. Values after memsetn"); a char (or 0). Cannot use to set integers for (i = 0; i < 5; ++i) (other than 0) in an array. printf(" a[%d] = %d , ", i, a[i]); // remove x from memory free(a); for timing, see example at return 0; Student/Examples/chap 1/test. Mem. Int. c } 2 -39

buffer set big. Mem 1 = (int *)malloc(50*1024*sizeof(int)); big. Mem 2 = (int *)malloc(50*1024*sizeof(int));

buffer set big. Mem 1 = (int *)malloc(50*1024*sizeof(int)); big. Mem 2 = (int *)malloc(50*1024*sizeof(int)); getrusage(RUSAGE_SELF, &usage); start = usage. ru_utime; printf("Started at: %ldn", start. tv_sec, start. tv_usec); for (i = 0; i < 50*1024; i++) big. Mem 1[i] = 0; getrusage(RUSAGE_SELF, &usage); end 1 = usage. ru_utime; Loop took over 300, 000 μsec barr@adar: ~/Student/Examples/chap 1$ tm Started at: 0: 0 Ended loop at: 0: 324020 Ended memset at: 0: 324020 memset took no discernable time printf("Ended loop at: %ldn", end 1. tv_sec, end 1. tv_usec); memset(big. Mem 2, 0, 50*1024); getrusage(RUSAGE_SELF, &usage); end 2 = usage. ru_utime; See Student/comp 210/examples/chap 1/test. Mem. Int. c 2 -40

2 D Arrays #include <stdio. h> #define COLS 5 #define ROWS 3 /* function

2 D Arrays #include <stdio. h> #define COLS 5 #define ROWS 3 /* function prototype */ void vector_add(int a[][SIZE], int n); main() { int i, j; int arr[ROWS][COLS]; You DO have to specify the size of all dimensions in an array that is a parameter EXCEPT the first. printf("Enter in the first row (5 values): "); for (i = 0; i < ROWS; i++){ for (j = 0; j < COLS; j ++) { scanf("%d", &arr[i][j]); } if (i < num. Rows -1) printf("n. Enter in the next row: "); } fprintf(stderr, "Calling vector_addn"); vector_add(arr, 3); printf("n"); printf("Good bye!n"); } 2 -41

2 D Arrays /* cannot return an array! */ void vector_add(int a[][SIZE], int n)

2 D Arrays /* cannot return an array! */ void vector_add(int a[][SIZE], int n) { int i, j; int ans[n]; /* initialize ans */ for (i = 0; i < n; i++) ans[i] = 0; fprintf(stderr, "in vector_addn"); /* sum the rows */ for (i = 0; i < n ; i++) for (j = 0; j < SIZE ; j++) ans[i] = ans[i] + a[i][j]; printf("The sum of each row is: n"); for (i = 0; i < n; i++) printf("%d ", ans[i]); printf("nn"); } Cannot return an array. Well, you can return a pointer that points to an array, but we won’t go there. Yet. 2 -42

2 D arrays and Pointers #include <stdlib. h> line #include <stdio. h> 0 1

2 D arrays and Pointers #include <stdlib. h> line #include <stdio. h> 0 1 2 3 int main(){ int *line[5], *ptr; int n, i; for (n = 0; n < 5; n++) line[n] = (int *)malloc(4*sizeof(int)); for (n = 0; n < 5; n++){ for (i = 0; i < 4; i++) line[n][i] = n * i; must do a malloc for } each element of the line printf( "The numbers are: n"); array. for (n = 0; n < 5; n++){ for (i = 0; i < 4; i++){ printf("%d ", line[n][i]); } printf("n"); } } 4 2 -43

2 D arrays and Pointers #include <stdlib. h> #include <stdio. h> int main(){ int

2 D arrays and Pointers #include <stdlib. h> #include <stdio. h> int main(){ int *line[5], *ptr; int n, i; for (n = 0; n < 5; n++) line[n] = (int *)malloc(4*sizeof(int)); for (n = 0; n < 5; n++){ ptr = line[n]; for (i = 0; i < 4; i++) //line[n][i] = n * i; *ptr++ = n * i; } Same as previous slide printf( "The numbers are: n"); using pointer syntax for (n = 0; n < 5; n++){ ptr = line[n]; for (i = 0; i < 4; i++){ printf("%d ”*ptr++, ); } printf("n"); } } but 2 -44