04/21/23 Course material created by D. Woit 1
CPS 393Introduction to Unix and C
START OF WEEK 9 (C-3)
04/21/23 Course material created by D. Woit 2
Pointers • Pointer is a data type which allows storage of location (address) of
data rather than data itself.• int main(void) { • int Num;• int *NumPtr;
• Num=5;• NumPtr = &Num;• printf(" %d \n", *NumPtr );• *NumPtr = 7;• printf(" %p %d %d \n", NumPtr, *NumPtr, Num );
• return(0);• } • NumPtr is a "pointer to int" • &Num is the address of variable Num (1200 here)• *NumPtr is the value at address in NumPtr (de-reference NumPtr)• or, what NumPtr "points to"
04/21/23 Course material created by D. Woit 3
• After statements Num=5; NumPtr = &Num; memory allocation is;• 1200 1204 1208 ... 1531 - memory addresses
• ------------------------ ---------------• ... | 5 | | | ... |1200 | - memory storage• ------------------------ ----------------• Num NumPtr
• After statement *NumPtr = 7; memory allocation is:
• 1200 1204 1208 ... 1531 - memory addresses
• ------------------------ ---------------• ... | 7 | | | ... |1200 | - memory storage• ------------------------ ----------------• Num NumPtr
04/21/23 Course material created by D. Woit 4
Pointers and Arrays • an array name is an address (i.e., a pointer)• i.e. it is address of the 1st item of the array• Code in ptr1.c• int main(void) { • int A[5] = {1,2,3,4,5};• int *p;• p=A;• printf("%d %d %d ", *p, *(p+1), *(p+2) );• putchar('\n');• printf("%d %d %d ", p[0], p[1], p[2] );• putchar('\n');• printf("%p %p %p ", p, p+1, p+2 );• printf("\nsize of int: %d\n",sizeof(int));• return(0);• }
04/21/23 Course material created by D. Woit 5
• int A[5] = {1,2,3,4,5};• 100 104 108 112 116 ... 236 ... …. 300• ------------------------ ----- ------ ------• | 1 | 2 | 3 | 4 | 5 |... … | |....... |100|• ------------------------ ----- ----- -------• A[0] A[1] A[2] A[3] A[4] A• int *p;• 100 104 108 112 116 ... 236 ... 300• ---------------------------- -------- -----• | 1 | 2 | 3 | 4 | 5 |... | |... |100|• -------------------------- ---- -----------• A[0] A[1] A[2] A[3] A[4] p A• • p=A;• 100 104 108 112 116 ... 236 ... 300• ----------------------------- ----- ---• | 1 | 2 | 3 | 4 | 5 |... |100|... |100|• ------------------------ ----- ------ -----• A[0] A[1] A[2] A[3] A[4] p A•
04/21/23 Course material created by D. Woit 6
• Discussion of previous example in ptr1.c• printf("%d %d %d ", *p, *(p+1), *(p+2) );• putchar('\n');• printf("%d %d %d ", p[0], p[1], p[2] );• putchar('\n');• printf("%p %p %p ", p, p+1, p+2 );
• 1 2 3• 1 2 3• 100 104 108 //assuming above storage placement
• why 104 ? 4 byte ints on our machine--use sizeof(int) to see.• ^ sizeof is a keyword (built-in like "for")• depends on type of p. • if int *p then p+1 is p+4bytes• if char *p then p+1 is p+1byte•
04/21/23 Course material created by D. Woit 7
Pointers cont.• Wrong usage , see ptrerr.c :• char B[] = "bcd";• char *p = B; /*initialize ptr to address of B[0] or ...*/• /*or: char *p = &B[0]; */• assuming &B[0] is 1000, what is the output of:• printf("%p %p %p ", p, p+1, p+2 ); • SAME THING:• char B[] = "bcd";• char *p;• p=B; /*or p=&B[0]*/• Note p[1] same as B[1] same as *(p+1) i.e., 'c' • p[0] same as B[0] same as *p i.e., 'b'•
04/21/23 Course material created by D. Woit 8
• //Source: cptr.c• char S[9]="Pointers";• char *cptr;• cptr=S; # try to omit this line and compile and then run• while ( putchar(*cptr++) ); //putchar returns the char it printed• //this prints the '\0' but the following• //do not:• // or, more clearly• // while ( *cptr ) putchar(*cptr++);• // or even more clearly• // while ( *cptr != '\0' ) putchar(*cptr++);• // or even more clearly• // while ( *cptr != '\0' ) {• // putchar(*cptr);• // cptr++;• // }• •
04/21/23 Course material created by D. Woit 9
• /*Source: sample12d.c */• /*Input: a string max length 39 */• /*Output: the string in upper case */• /*Purpose: convert string to upper case */• #include <ctype.h>• #include <stdio.h>• int main(void) {• char str[40], *p; • printf("Enter a string: ");• (void) gets(str); • p=&str[0]; /*or p=str */• while ( *p != '\0' ) { /*or while(*p) */• *p++ = toupper(*p);• }• printf("%s\n",str);• exit(0);• }•
Note: the body of the while stmt is exactly same as { *p = toupper(*p); p++; }
04/21/23 Course material created by D. Woit 10
• /*Source highest.c*/• #define ELTS 5• #include <stdio.h>• int main(void) {• int i, *high, *p;• int array[ELTS]={200,34,78,600,45};• high=array;• p=array;• for ( i=1; i< ELTS; i++ ) {• p++;• if (*p > *high) high = p;• }• printf("the highest number is %d \n", *high);• printf("at address %p \n", high);• printf("at index %d of array \n", high-array);• exit(0);• }
04/21/23 Course material created by D. Woit 11
Pointers and String Constants • when compiler encounters a string constant, it stores it in a string
table and generates a pointer to the string (address)• char *p;• p="A String";• printf(p); • Note that the following is BAD:• char *p;• gets(p);• printf(p);• Why bad?• p has no storage allocated to it. It might "work" sometimes• and not work other times because its storage is overwritten,• or because the value IN p does not point to an accessible• storage location.
04/21/23 Course material created by D. Woit 12
Pointers as Parameters • all parameters in C are passed by value• However, we can fake pass by reference by passing the
*address*, and then use * inside function to modify the data• this explains: scanf("%d", &num ); • Example:• int A[20];• A is the address of the array (address of A[0])• Thus, a function call such as • sum(A)• passes the *address*; so any changes to A within sum• are retained (i.e., like call by reference.)
04/21/23 Course material created by D. Woit 13
(code in callByRef.c)
• Example for call by reference:
• void add1 (int *x) {• *x = *x + 1 ;• }• ...• int a=5;• add1(&a);• printf("a is %d\n",a);•
04/21/23 Course material created by D. Woit 14
• /*Source: sample14.c*/• void swap(int *arg1, int
*arg2);• int main(void) {• int i=0, j=2;• printf("i is %d, j is %d \n",
i,j);• swap(&i,&j);• printf("i is %d, j is %d \n",
i,j);• exit(0);• }•
• /*Function: swap • Purpose: swap values of
2 integers• Input: addresses of the 2
integers to swap• Output: none• */• void swap(int *arg1, int
*arg2 ) {• int temp;• temp = *arg1; • *arg1=*arg2;• *arg2=temp;• }• prints?
04/21/23 Course material created by D. Woit 15
• /*Source: sample15.c */• void swap1 (int A[2] );• int main(void) {• int A[2]={1,2};• printf("%d %d \n", A[0],
A[1] );• swap1(A);• printf("%d %d \n", A[0],
A[1] );• exit(0);• }•
• void swap1 (int A[2] ) {• int temp;• temp = A[0];• A[0] = A[1];• A[1] = temp;• }
• These function prototypes are all the same:
• void swap1(int A[2]);• void swap1(int A[]);• void swap1(int *A);
04/21/23 Course material created by D. Woit 16
A function may have type "pointer to type"
• /*Source: sample16.c*/• #include <stdio.h>• #include <string.h>• char *addXX(char *S);• int main(void) {• char str1[25], *str2;• gets(str1); • str2=addXX(str1);• puts(str2);• exit(0);• }
• char *addXX(char *S) {• strcat(S,"XX");• return (S);• }• Does str2 have storage
allocated? No need.• What happens if the
user enters a string that is more than 23 chars long?
04/21/23 Course material created by D. Woit 17
HMWK• 1. Write a function with prototype: void swap_string1(char
*A, char *B); • The function swaps the strings in A and B. It does this by
looping through the string(s) and swapping individual characters. If your function needs to know the length of a string, it can use strlen from string.h, or it can just look for the '\0' at the string end.
• Write a main program to test swap_string1. Your main must allocate all the storage required for the strings. DO NOT copy junk from memory.
• Only copy characters from the strings.
04/21/23 Course material created by D. Woit 18
Multiple Indirection • char **mp, *p, ch;
• 1080 ... 1248 ... 1272
• ----------- ---------- ----------• ... | | ... | | ... | | • ----------- ---------- ----------• mp p ch
• p=&ch; mp=&p; **mp='A'; • 1080 ... 1248 ... 1272 • ----------- ---------- --------------• ... | 1248 | ... | 1272 | ... | A | • ----------- ---------- ---------------• mp p ch
• This is same as simply ch= ‘A’
04/21/23 Course material created by D. Woit 19
Precedence of Array & Ptr operations:• Operator Precedence Associativity (see below)• () [] -> . left• ++ -- sizeof ! ~ (type) + - * & right (ALL ARE UNARY OPERATORS)
• * / % left• + - left (BINARY)• << >> left • < <= > >= left • == != left• & left (BINARY)• ^ left • | left• && left • || left • ?: right• = += -= *= /= %= &= ^= |= <<= >>= right• , left
04/21/23 Course material created by D. Woit 20
• Associativity means if 2 operators with equal precedence are in an expression, they will be done from left-to-right if left-assoc and from right-to-left if right-assoc
• ~ is one's complement (unary)• ! is logical not: if (!x)• ++ -- are unary inc/decrement prefix or postfix: i++ or ++i• unary * unary & are ptr dereference, address of• << >> left bit shift, right bit shift• && || logical and, or• & | ^ bitwise and, or, Xor• ?: ternary operation (for conditional e.g., z = (a>b) ? a : b ;• resolves to: z = a OR z = b , depending
04/21/23 Course material created by D. Woit 21
• Note:• **a means *(*a)• &(&a) means &a (&&a is invalid)• &a[1] means &(a[1])• *a[1] means *(a[1])
•
04/21/23 Course material created by D. Woit 22
Dealing with errors
Compile this program with gcc –lm –o sqrt sqrt.c
• //source sqrt.c• #include <stdio.h>• #include <errno.h>• #include <math.h>• #define POSITIVE 25• #define NEGATIVE -25•
04/21/23 Course material created by D. Woit 23
• int main(void){• double ret;• errno = 0;• ret = sqrt(NEGATIVE);• if (errno == EDOM) /*EDOM Signifies Domain Error*/• //printf("Domain Error : Invalid Input To Function\n");• perror("sqrt");• else • printf("Valid Input To Function\n");• errno = 0;• ret = sqrt(POSITIVE);• if (errno == EDOM) • printf("Domain Error : Invalid Input To Function\n");• else • printf("Valid Input To Function\n");• return 0;• }
• If a function sets errno, it is stated in man page. e.g.,• man scanf• then search for errno • then search for ERROR
Top Related