Lecture #3: Pointers Reading: Holmes, Chapters 8 and 9 Handouts: Pointers, Confusion, and All That; num.c; prenv.c Homework: Adssignment #2, due Thursday, October 16, at 6PM 1. Greetings and felicitations 2. Review precedence table quickly 3. Pointers and addresses … draw this, show simple example: for(i = 0, p = x; *p; i++, p++); … * operator, & operator … pointer arithmetic; why p - x is only legal operation; discuss p - 1, p + 1 4. Pointers and Arrays … rework above example as arrays … describe: pointer constant (array name), pointer variable … difference between int *x and int x[1] … multiple dimensions: p = &a[0][0] with int a[2][3] 5. Multiply indirect pointers … show array of pointers … walk through (and draw) pointer confusion 6. Strings … NUL byte … show strcat, strcpy (do shortest versions of this), index … do sprintf(buf, ģ%s: check out line %dē, filename, lineno); 7. Command-line interface as example of pointer args … argv, argc; show num x y z … envp; show printenv PATH 8. Arrays vs. Pointers again … allocation of arrays … malloc, free for pointers … realloc: warn about p = realloc(p, 10000) Pointers, Confusion, and All That This very short, very confusing program shows the type of code that programmers who become addicted to pointers in C can write. It also is an excellent exercise in using pointers; if you can read this and figure out what it prints, you will be able to read and understand (almost) any use of C pointers! This exercise is from Alan Feuer's marvelous book The C Puzzle Book. char *c[] = { "ENTER", "NEW", "POINT", "FIRST" }; char **cp[] = { c+3, c+2, c+1, c }; char ***cpp = cp; main() { printf("%s", **++cpp ); printf("%s ", *--*++cpp+3 ); printf("%s", *cpp[-2]+3 ); printf("%s\n", cpp[-1][-1]+1 ); } num.c This program prints a file, putting the file name and line number in front of each line. For example, if the file hello contains: hi there how are you? the command num hello prints hello, 1:hi there hello, 2:how are you? And now, the program! /* * program to print a file with file name and line number * prefixing each line * invocation: * num print stdin with line numbers * num arg1 ... print contents of arg1 with line numbers * exit code: number of files not opened * author: Matt Bishop, bishop@cs.ucdavis.edu, 9/16/96 */ #include #include /* * print the given file, with the file name and line * number in front * arguments: fn pointer to file name * fp file pointer */ void cat(char *fn, FILE *fp) { register int c; /* input character */ register int lno = 0; /* line number */ register int nlstate = 1; /* 1 if last char a newline */ /* * read the file */ while((c = getc(fp)) != EOF){ /* was the previous char a newline */ if (nlstate){ /* one more line */ lno++; /* print the line number and file name */ if (fn == NULL) printf("%4d: ", lno); else printf("%s,%4d: ", fn, lno); /* we now clear the record of the newline */ nlstate = 0; } /* print the character */ putchar(c); /* if it's a newline, set the flag */ if (c == '\n') nlstate = 1; } } /* * the main routine */ int main(int argc, char *argv[]) { register int nerr = 0; /* nuber of files not opened */ register char **a; /* used to walk argument list */ register FILE *fp; /* pointer to file being processed */ /* * no argument -- use stdin */ if (argc == 1){ cat(NULL, stdin); return(EXIT_SUCCESS); } /* * walk the arg list, doing each file */ for(a = &argv[1]; *a != NULL; a++) /* open the file */ if ((fp = fopen(*a, "r")) == NULL){ /* oops ... say what happened */ perror(*a); nerr++; } else{ /* print the file */ cat(*a, fp); } /* * status is the number of files not opened */ return(nerr); } prenv.c This program prints all environment variables that are exported to the subprocess. If no arguments are given, it prints all the environment variables and their values; if arguments ar givn, it prints the values of those environment variables. /* * program to print environment variables * invocation: * prenv print argument list * prenv arg1 ... print value of argument(s) * exit code: number of environment variables not found * author: Matt Bishop, bishop@cs.ucdavis.edu, 9/16/96 */ #include #include #include int main(int argc, char *argv[], char *envp[]) { register int i; /* counter in for loops */ register int narg; /* number of current argument */ register int len; /* length of current argument */ register int found; /* 1 if env. variable found */ register int exstat = 0; /* exit status code */ /* * no arguments; just print the environment * variables and their values */ if (argc == 1){ /* just loop and print */ for(i = 0; envp[i] != NULL; i++) printf("%s\n", envp[i]); /* all done! */ return(EXIT_SUCCESS); } /* * arguments given; just print the values * associated with these named variables */ for(narg = 1; argv[narg] != NULL; narg++){ /* just an optimization ... */ len = strlen(argv[narg]); /* assume no such variable */ found = 0; /* * now look for the variable */ for(i = 0; envp[i] != NULL; i++) /* see if this one is it*/ if (strncmp(envp[i], argv[narg], len) == 0){ /* name= means value follows = */ if (envp[i][len] == '='){ printf("%s\n", envp[i] + len + 1); found++; } /* name means value is empty */ /* anything else, it doesn't match */ else if (!envp[i][len]){ putchar('\n'); found++; } } /* * did we find it? */ if (!found){ /* nope -- print error message */ fprintf(stderr, "%s: no such variable\n", argv[narg]); /* one more unknown environment variable */ exstat++; } } /* * return number of unknown environment variables */ return(exstat); } Pointers, Confusion, and All That ECS 40 ­ FALL 1997 Page 3 num.c ECS 40 ­ FALL 1997 Page 4 prenv.c ECS 40 ­ FALL 1997 Page 8