1 查找地址:&运算符
int pooh = 24;
printf("%d %p\n", pooh, &pooh); // 24 0B76
2 间接运算符
int *ptr;
int pooh = 24;
int val;
ptr = &pooh; // ptr指向pooh,把pooh的地址给ptr
val = *ptr; // 找出ptr指向的值,val=24
3 声明指针
声明指针变量时必须指定指针所指向变量的类型,因为不同的变量类型占用不同的存储空间,一些指针操作要求知道操作对象的大小。
int *pi;
char *pc;
float *pf;
指针的简单理解:
可以将int *pi分成三部分看
pi:代表指针,赋值的话要提供一个地址,查找地址通过&运算符,即pi = &pooh;
*pi:代表int类型的变量,赋值的话要提供一个值,即*pi = 24;
int *pi:代表指针变量
类型说明符表明了指针所指向对象的类型,星号(*)表明声明的变量是一个指针。int *pi声明表示pi是一个指针,*pi是int类型。
#include<stdio.h>
void interchange(int *u, int *v);
int main(void) {
int x = 5, y = 10;
printf("Orignially x = %d and y = %d\n", x, y);
interchange(&x, &y); // 将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;
}
4 数组和指针
为何需要声明指针的类型?
#include<stdio.h>
#define SIZE 4
int main(void) {
short dates[SIZE];
short *pti;
short index;
double bills[SIZE];
double *ptf;
pti = dates; // 指向数组第一个元素的地址
ptf = bills;
// pti+index:*pti是short类型,short类型占用2个字节,pti指针+1表示增加一个存储单元,每次增加2个字节地址
// ptf+index:*ptf是double类型,double类型占用8个字节,每次增加8个字节地址
// 如果不声明指针类型,就无法知道增加的字节地址
for (index = 0; index < SIZE; index++) {
printf("i=%d,%10p,%10p", index, pti+index, ptf+index);
}
return 0;
}
只有在函数原型或函数定义头中,才可以用int arr[]代替int *arr。
int arr[]和int *arr都表示arr是一个指向int的指针
下面的函数原型声明是等价的:
int sum(int arr[], int n);
int sum(int *arr, int n);
获取数组元素之和的两种方式
#include<stdio.h>
#define SIZE 5
int sum1(int arr[], int n);
int sum2(int *start, int *addr);
int main(void) {
int marbles[SIZE] = {20, 10, 5, 39, 4};
long answer;
answer = sum1(marbles, SIZE);
answer = sum2(marbles, marbles + SIZE);
printf("%d", answer);
return 0;
}
// 数组形参函数
int sum1(int arr[], int n) {
int total;
for (int i = 0; i < n; i++) {
total += arr[i];
}
return total;
}
// 指针形参函数
int sum2(int *start, int *addr) {
int total;
while (start < end) {
total += *start;
start++;
}
return total;
}
5 指针操作
#include<stdio.h>
int main(void) {
int arr[5] = {100, 200, 300, 400, 500};
int *ptr1, *ptr2, *ptr3;
ptr1 = arr; // 指针指向数组的首地址,等价*ptr1 = arr[0], *(ptr2 + 1) = arr[1]
ptr2 = &arr[2];
// prt1 + 4 = 0x7fff5fbff8d0, *(ptr1 + 4) = 500
ptr3 = ptr1 + 4; // 指针加法
printf("ptr1 + 4 = %p, *(ptr1 + 4) = %d\n", ptr1 + 4, *(ptr1 + 4));
// *ptr1 = 200
ptr1++; // 递增指针
ptrintf("*ptr1 = %d", *ptr1);
// *ptr2 = 100
ptr2--; // 递减指针
printf("*ptr2 = %d", *ptr2);
// *ptr1 = 100
--ptr1; // 恢复初始值
printf("*ptr1 = %d", *ptr1);
// *ptr2 = 200
++ptr2; // 恢复初始值
printf("*ptr2 = %d", *ptr2);
// 一个指针减去另一个指针
// ptr2 - ptr1 = 2
printf("ptr2 - ptr1 = %td", ptr2 - ptr1);
// 一个指针减去一个数
// 地址相同
printf("ptr3 - 2 = %p, &arr[2] = %p", ptr3 - 2, &arr[2]);
}
6 解引用未初始化的指针
int *pt;
*pt = 5; // 严重错误,因为pt未被初始化未开辟内存空间,它只是一个随机值,一般要配合malloc()与指针配合初始化开辟指针的内存空间
int arr[3];
int *ptr1, *ptr2;
有效语句: 无效语句:
ptr1++; arr++;
ptr2 = ptr1 + 1; ptr2 = ptr2 + ptr1;
ptr2 = arr + 1; ptr2 = arr * ptr1;