CS157 Pointers
int
, float
, pointer to int
)
int
is int *
float
is float *
int
is int **
int
is int ****
Declare and initialize in one step: int *p = &x;
-or-
int *p;
p = &x;
int a = 123; int *p = &a;
Physically, assuming a
lives at location 7689:
┌────┐ ┌───┐ p:│7689│ a:│123│ └────┘ └───┘
Or, thinking the contents of p
as a pointer rather
than as a number:
┌──┐ ┌───┐ p:│ ─┼────>a:│123│ └──┘ └───┘
It’s a variable that points to another.
int val; // regular int int *ptr; // pointer to an int
┌────┐ ┌────┐ ptr:│ ?? │ val:│ ?? │ └────┘ └────┘
It’s a variable that points to another.
int val; // regular int int *ptr; // pointer to an int ptr = &val; // ptr contains the address of val
┌──┐ ┌────┐ ptr:│ ─┼────>val:│ ?? │ └──┘ └────┘
It’s a variable that points to another.
int val; // regular int int *ptr; // pointer to an int ptr = &val; // ptr contains the address of val *ptr = 42; // Whatever ptr refers to becomes 42
┌──┐ ┌────┐ ptr:│ ─┼────>val:│ 42 │ └──┘ └────┘
┌──┐ ┌───┐ ┌──┐ │ ─┼────>│123│<─────┼─ │ └──┘ └───┘ └──┘ p x q
int x, *p = &x, *q = &x; x=4; printf("x=%d\n", x); x=x+3; printf("x=%d\n", x); *p = 42; printf("x=%d\n", x); *q = 8; printf("x=%d\n", x); *&x = *q + *p; printf("x=%d\n", x); x = *q**p; printf("x=%d\n", x);
x=4 x=7 x=42 x=8 x=16 x=256
i
and j
i
has the smaller, and j
has the larger value.
void swap(int *a, int *b); int main() { int i=2, j=5; swap(&i, &j); return 0; }
┌──┐ ┌───┐ a:│ ─┼────>i:│ 2 │ └──┘ └───┘ ┌──┐ ┌───┐ b:│ ─┼────>j:│ 5 │ └──┘ └───┘
By using pointers we can make ONE more generic swap routine, using “Pass by reference” instead of “Pass by value”
void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } int main() { int washington=1, lincoln=16; swap(&washington, &lincoln); printf("%d %d\n", washington, lincoln); }
16 1
NULL
is a pointer to NOTHING!
ptr = NULL;
ptr
isn’t pointing to anything useful.
NULL
when it can't find the character.
int
gives you a pointer
int
gives you a pointer
int
int data[] = {11,22,33,44,55,66,77,88}; int *p; p = data; printf("%d\n", *p); p += 4; printf("%d\n", *p); p--; printf("%d\n", *p); p = &data[2]; printf("%d\n", *p);
11 55 44 33
a[i]
is equivalent to *(a+i)
a[i]
and i[a]
?
i[a]
legal?
double a[] = {1.2, 3.4, 5.6, 7.8}; printf("%.2f\n", a[2]); printf("%.2f\n", *(a+2)); printf("%.2f\n", *(2+a)); printf("%.2f\n", 2[a]);
5.60 5.60 5.60 5.60
a &a[0]
double a[] = {1.2, 3.4, 5.6, 7.8}; double *p; p = a; printf("%.3f\n", *p); p = &a[0]; printf("%.3f\n", *p);
1.200 1.200
void p3chars(char *p) { printf("%c%c%c\n", *p, *(p+1), *(p+2)); } int main() { char buf[] = "abcdefghij"; p3chars(&buf[0]); // abc p3chars(&buf[2]); // cde p3chars(buf); // abc return 0; }
a␜␜3␜␜b␜␜4␜␜c c␜␜3␜␜d␜␜4␜␜e a␜␜3␜␜b␜␜4␜␜c
char word[100]; char * wptr = word; // or char* wptr; or char *wptr;
wptr | word | &word[0] |
(wptr+n) | word+n | &word[n] |
*wptr | *word | word[0] |
*(wptr+n) | *(word+n) | word[n] |
Strings are char arrays, but arrays are just pointers, so a string is just a pointer to char(s)
strcpy(char *dest, char *src)
src
to dest
strcat(char *dest, char *src)
src
onto the end of dest
int strcasecmp(const char *s1, const char *s2)
s1
to s2
, ignoring case
strncpy(char *dest, char *src, int max)
max
chars from src
to dest
strncat(char *dest, char *src, int max)
max
chars from src
onto the end of dest
int strncasecmp(const char *s1, const char *s2, int max)
max
chars from s1
to s2
, ignoring case
strchr(char *s, char c)
c
in the string s
, or NULL
if it isn’t there
strstr(char *haystack, char *needle)
needle
in
the string haystack
, or NULL
if it isn’t there!
const char *p = strchr("My dog has fleas", 'g'); const char *q = strstr("My dog has fleas", "has"); printf("p=%s\n", p); printf("q=%s\n", q);
p=g has fleas q=has fleas
const char *p = "elephant"; const char *q = "elephant"; if (p == q) puts("Same"); else puts("Different");
Same
Pointers can also be used to return multiple values, instead of just one.
void func(int *a, int *b, int *c) { *a = 1; *b = 4; *c = 9; } int main() { int number=6, thingy=7, value=8; func(&number, &thingy, &value); printf("%d %d %d\n", number, thingy, value); return 0; }
1 4 9
A function that takes two numbers and returns the quotient and the remainder!
void long_division(int *quotient_ptr, int *remainder_ptr, int dividend, int divisor) { *quotient_ptr = dividend / divisor; *remainder_ptr = dividend % divisor; } int main() { int quot, rem; long_division(", &rem, 40, 3); printf("quotient is %d, remainder is %d\n", quot, rem); return 0; }
quotient is 13, remainder is 1
int miles, nums[25]; int *a = &45; // invalid — attempt to take address of a value int *b = &(miles+10); // invalid — attempt to take address of a value int *c = &miles + 10; // semi-valid — 10 is added to address of miles int *d = &nums; // invalid — nums is an address, so no address of the address! int *e = nums; // valid
NULL pointers are not to be read from, or written to:
int *p = NULL; printf("Read from NULL: %d\n", *p);
SIGSEGV: Segmentation fault
int *p = NULL; puts("Let’s write to a NULL pointer!"); *p = 0;
SIGSEGV: Segmentation fault