510 likes | 678 Views
Pointer. Dong- Chul Kim BioMeCIS CSE @ UTA. Addresses in Memory. Everything in memory has an address. C allows us to obtain the address that a variable is stored at. scanf() is an example using the address of a variable scanf("%d", & year);. Address in Memory.
E N D
Pointer Dong-Chul Kim BioMeCIS CSE @ UTA
Addresses in Memory • Everything in memory has an address. C allows us to obtain the address that a variable is stored at. • scanf() is an example using the address of a variable scanf("%d", &year);
Address in Memory • Preceding a variable name by an ampersand, known as the address operator, will return its address: #include <stdio.h> int main(void) { int x; /* notice the format specifier in printf() for an address is %p */ printf("The address for the memory allocated to x is %p\n", &x); return 0; }
hexadecimal (or called base-16) 0123456789ABCDEF • The address for the memory allocated to x is 0012FF60 in the previous exam. • For 32 bits system the 0012FF60 hexadecimal will be converted to 32 bits binary (one hex character represented by 4 bits).
Data type • Initialization • Updating Pointer • A pointer is a variable whose value is a memory address. • Note the type of a pointer indicates the type of variable which it points to. • E.g., int * (called pointer-to-int type) should be initialized to point to a variable of type int. • Similarly, we have char*, float *, …… • Given a pointer variable, assignment can be done by using: int * ptr = &pooh; /*assigns pooh’s address to ptr, we say ptr points to pooh*/ ptr = &bah; /*make ptr point to some other variables*/
#include<stdio.h> int main(void) { int num = 3, num1 = 5; int* numptr; /* numptr is a pointer */ printf("content of num is %d\n", num); printf("address of num is %p\n", &num); printf("address of num1 is %p\n", &num1); numptr = # /* initialize numptr with the address of num */ printf("content of numptr is %p\n", numptr); numptr = &num1; printf("content of numptr is %p\n", numptr); return 0; }
Indirection operator • Pointers allow us to modify content in memory by using indirection operator (or called dereference operator). • Putting an asterisk before your pointer variable • See the example in the next slide
bah 10 • What’s going here? #include <stdio.h> int main(void) { int bah = 10, val; int* ptr = &bah; val = *ptr; printf("The value of val is %d.\n", val); return 0; } val 10 ptr 0012FF60
Pointers • We can use pointers in much the same way we do the variables that they point to. int main(void) { int a = 3, b = 3; /* a and b start with equal values */ int* bptr = &b; /* we’ll modify b using a pointer */ a *= 4; *bptr *= 4; printf("a is %d, b is %d\n", a, b); a--; (*bptr)--; /* parentheses are necessary here to override the order of precedence */ printf("a is %d, b is %d\n", a, b); return 0; }
Define multiple pointers together • Wrong! int * a, b; • Instead, you should use int * a, *b;
Pointers to Pointers • Pointers can contain the address of another pointer. int main(void) { int num = 5; int* numptr = # int** ptr2 = &numptr; /* notice the two asterisks */ printf(" num is %d\n", num); printf("*numptr is %d\n", *numptr); printf(" **ptr2 is %d\n", **ptr2); return 0; }
Comparing Pointers • Note the difference between comparing the contents of pointers and the variables that pointers point to. • To compare the addresses stored in pointers, use • if(numptr == valptr) • To compare the values of the variables that pointers point to, use • if(*numptr == *valptr)
Initializing Pointers to NULL • Repeat again here: you have to initialize a variable before you use it. • If there is no specific initialization, we usually initialize a pointer to NULL (in uppercase). Later we can check the value of that pointer to know whether we have pointed it to any variable. • If you didn’t initialize your program may not pass the compilation.
Initializing Pointers to NULL #include <stdio.h> int main(void) { int num = 3; int* numptr; numptr = NULL;/*Try another example without this statement*/ if (numptr != NULL) printf("num is %d\n", *numptr); else printf("Oops. numptr has a value of %p.\n", numptr); return 0; }
Pointers and Functions • Previously, we made function calls like this: int x = 3; int y; y = do_something(x); • In this case, a copy of the variable’s value are passed to the function in a process called pass by value. • Changes made to the copy do not affect the original value.
Pointers and Functions • Passing pointers to a function will allow us to change the value of the original variable, called pass by reference, • We do this by passing the variable’s address to the function. • We already know passing array to a function is pass by reference. • What’s the association between array and pointer?????
Pointers and Functions #include<stdio.h> void interchange(int * u, int * v); int main(void) { int x = 5, y = 10; printf("Originally x = %d and y = %d.\n", x,y); interchange(&x, &y); printf("Now x = %d and y = %d.\n", x,y); return 0; } void interchange(int * u, int * v) { int temp; temp = *u; *u = *v; *v = temp; }
Pointers and Functions #include <stdio.h> void tripleNum(int*); /* notice the function argument has a type of int * */ int main(void) { int num = 8; int* numptr = # printf("before the function call, num is %d\n", num); tripleNum(numptr); /*or simply use &num*/ printf("after the function call, num is %d\n", num); } void tripleNum(int* aptr) /* pass by reference */ { *aptr = 3 * *aptr; /* first asterisk is for multiplication, second is to dereference the pointer */ }
Difference between copy by value and copy by reference #include <stdio.h> void fx(int x); void fxptr(int* x); int main(void) { int x = 7; printf("outside: x is at %p\n", &x); fx( x ); fxptr(&x); } void fx(int x) { printf("inside fx(): x is at %p\n", &x); } void fxptr(int* x) { printf("inside fxptr(): x contains %p\n", x); }
Arrays, Part 2 • We have already learned how to work with arrays using subscript notation. • Example: float myData[] = {3.5, 4.0, 9.34}; myData[0] += 2; printf("myData[0] is %3.1f\n", myData[0]);
Pointers and Arrays • The array name evaluates to the address of the first element in the array. int data[] = {5, 6, 7}; int* dataptr = data; /* notice that we don’t use the ampersand here */ int* firstptr = &data[0]; /* we use & here since data[0] evaluates to a number */ printf("*dataptr is %d, *firstptr is %d\n", *dataptr, *firstptr);
Pointer Arithmetic • Since arrays consist of contiguous memory locations, we can increment (or decrement) the addresses to move through the array. int data[] = {5, 6, 7}; int i; for (i = 0; i < 3; i++) printf("the value at address %p is %d\n", (data + i), *(data + i));
Pointer Arithmetic • In the previous example, we also used pointer arithmetic in the line printf("the value at address %p is %d\n", (data + i), *(data + i)); • Since data was declared to be an array of ints, the expression (data + i) adds i * sizeof(int) • to the address of data to get the location of the next int. • This is a reason why we can’t mix types, e.g., point an int* type pointer to a variable of type double.
Pointer Arithmetic • We can use pointer arithmetic with pointers to non-array int some; int* someptr = &some; int data[] = {5, 6, 7}; int* dataptr = data; printf("pointer address = %p, next address = %p\n", someptr, someptr + 1); printf("pointer address = %p, next address = %p\n", dataptr, dataptr + 1); type variables as well.
Pointer Arithmetic • Pointer arithmetic handles the task of determining the address of the next element in the array. char chararray[] = {68, 97, 114, 105, 110}; /* 1 byte each */ int intarray[] = {10, 11, 12, 13, 14}; /* 4 bytes each */ int i; printf("chararray intarray\n"); printf("-------------------\n"); for(i = 0; i < 5; i++) printf("%p, %p\n", (chararray + i), (intarray + i));
Incrementing Pointers • When you use the increment and decrement operators with pointer variables, you need to be careful that we order the dereference and increment/decrement operators properly. • ∗, ++ and -- are at the same level of precedence and are evaluated from right to left. • The primary issue is whether we wish to increment the address stored in the pointer, or increment the value at the address in the pointer.
Arrays and Functions, Part 2 • Earlier we learned how to pass the address of a non-array type variable, for example int myValue = 5; someFunct(&myValue); • We’ve already been passing the address of the first member of an array when we did something like this: float data[] = {1, 2, 3}; anotherFunct(data);
The subscript style of having 1D arrays as function parameters used square brackets, e.g., void somefunction(int data[]) { } • The pointer style of having 1D arrays as function • parameters is this: void somefunction(int* data) { }
#include <stdio.h> • int main(void) • { • int intArray[] = {8, 4, 13, 7}; • double doubleArray[] = {93.2, 67.12, 2, 19.03}; • int i; • int* ptrI = intArray; • double* ptrD = doubleArray; • for(i = 0; i < 4; i++) • printf("%p = %2d, %p = %5.2f\n", &intArray[i], intArray[i], • &doubleArray[i], doubleArray[i]); • for(i = 0; i < 4; i++) • { • printf("%p = %2d, %p = %5.2f\n", ptrI, *ptrI, ptrD, *ptrD); • ptrI++; • ptrD++; • } • }
Arrays of Pointers • We can have an array whose members are pointers, in this example pointers-to-int. int* data[3]; int i; int x = 5; int y = 89; int z = 34; data[0] = &x; data[1] = &y; data[2] = &z; for(i = 0; i < 3; i++) printf("%d\n", *data[i]);
Outline • Functions, arrays and pointers • 2-dimentional arrays and pointers • More string functions
Define an array of a particular size #include <stdio.h> int main(void) { int n = 5; int m = 8; float a1[5];/*Yes*/ float a2[5*2+1];/*Yes*/ float a3[sizeof(int)+1];/*Yes*/ float a4[-4]; float a5[0]; float a6[2.5]; float a7[(int) 2.5];/*Yes*/ float a8[n];/*No for C89, but Yes for after C89*/ return 0; }
Function and array size • (1) a fixed array size in your function • (2) passing the array size as a second argument • (3) passing the address after the last element in the array
(1) a fixed array size in your function int sum(int *ar) { int i; int total = 0; for (i = 0 ; i < 10; i++) { total += ar[i]; } return total; }
(2) passing the array size as a second argument int sum(int *ar, int n) { int i; int total = 0; for (i = 0 ; i < n; i++) { total += ar[i]; } return total; }
(3) passing the address after the last element in the array #include <stdio.h> int sump(int * start, int * end); int main(void) { int marbles[] = {20, 14, 23, 54}; int answer; answer = sump(marbles, marbles + 4); printf("The sum of integers in marbles is %d.\n", answer); return 0; } int sump(int * start, int * end) { int total = 0; while(start < end) { total += *start; start++; } return total; }
sizeof( ) for array name in different places #include <stdio.h> int sump(int ar[], int n); int main(void) { int marbles[] = {20, 14, 23, 54}; int answer; printf("The size of marbles is %d bytes.\n", sizeof(marbles)); answer = sump(marbles, sizeof(marbles)/sizeof(int)); return 0; } int sump(int ar[], int n) { int i; int total = 0; for (i = 0 ; i < n; i++) { total += ar[i]; } printf("The size of ar is %d bytes.\n", sizeof(ar)); return total; }
Pointer operations • Assignment • Adding an integer to a pointer • Incrementing a pointer • Subtracting an integer from a pointer • Decrementing a pointer • Differencing: different from subtracting an integer from a pointer
Differencing of pointers int main(void) { int marbles[] = {20, 14, 23, 54}; int * ptr1, * ptr2; ptr1 = &marbles[0]; ptr2 = &marbles[3]; printf("There are %d elements between marbles[0] (inclusive) and marbles[3].\n", ptr2-ptr1); return 0; }
2-Dimentional array • int zippo[4][2]; • zippo, being the name of an array, is the address of the first element of the array. The first element of zippo is an array of two ints, so zippo is the address of an array of two ints. That is zippo has the same value as &zippo[0]. • Since zippo[0] is itself an array of two integers, so zippo[0] has the same value as &zippo[0][0], the address of its first element, an int. • In short, zippo[0] is the address of an int-sized object, and zippo is the address of a two-int-sized object. Because both the integer and the array of two integers begin at the same location, both zippo and zioop[0] have the same numeric value.
2-Dimentional array cont. • Adding 1 to a pointer or address yields a value larger by the size of the referred-to object. In this respect, zippo and zippo[0] differ, because zippo refers to an object two ints in size, and zippo[0] refers to an object one int in size. Therefore, zippo + 1 has a different value from zippo[0] + 1.
2-Dimentional array cont. • The general form for getting the address of any element of any row is *(array_name + row) + column • For example, when we write *(data + 1) + 2, we are saying “add the size of one row to the address of data, get the address of this, then add the size of two elements of a row to this”. • The general form for getting the value of any element of any row is *(*(array_name + row) + column)
String array #include <stdio.h> int main(void) { inti, j; char* text[4] = {"this", /* text[0] points to this word */ "is", /* text[1] points to this word */ "a", /* text[2] points to this word */ "string"}; /* text[3] points to this word */ char * tmp; for(i = 0; i < 4; i++) { j = 0; while (*(text[i] + j) != '\0') /* print each character */ { tmp = (text[i] + j++); printf("%c: %p ", *tmp,tmp ); /* note the %c */ } printf(" \n"); } return 0; }
String functions • strtok() • strcat() • strcpy()
strtok( ) • char *strtok( pointer-to-str1, pointer-to-str2); • The strtok() function returns a pointer to the next "token"found in str1 • str2 contains the delimiters that determine the token • strtok() returns NULL if no token is found. • In order to convert a string to tokens, the first call to strtok() should have str1 point to the string to be tokenized. All calls after this should have str1 be NULL.
strtok( ) cont. #include <stdio.h> #include <string.h> int main(void) { char str[] = "12333$q4tqrgtq$4524;lkj;$;lkj"; char delims[] = "$"; char *result = NULL; result = strtok( str, delims); while( result != NULL ) { printf( "result is \"%s\"\n", result ); result = strtok( NULL, delims); } return 0; }
strcat( ) • strcat() for string concatenation • Take two strings for arguments • A copy of the second string is tacked onto the end of the first, and this combined version becomes the new first string. • The second string is not altered. • The return type of strcat() is char *, the value of its first argument – the address of the first character of the string to which the second string is appended.
strcat( ) cont. #include <stdio.h> #include <string.h> int main(void) { char flower[80]; char addon[] = " is a cat."; scanf("%s", flower); strcat(flower, addon); printf("%s\n",flower); return 0; } • Note!!! strcar( ) not checking whether the first array is large enough to hold the second string. • strncat( ) (different from strcat( ) ) • strncat(bugs, addon, 5) will add the contents of the addon string to bugs, stopping when it reaches 5 additional characters or the null character, whichever comes first.
strcpy( ) • char * strcyp(char * s1, const char * s2) • This function copies the string (including the null character) pointed to by s2 to the location pointed to by s1. The return value is s1. • The strcyp( ) function has type char *, and it returns the value of its first argument – the address of a character. • The first argument need not point to the beginning of an array.