一、什么是指针
大多数现代计算机将内存分隔为字节(byte),每个字节可以储存8位的信息,每个字节都有唯一的地址,那么地址该怎么储存呢?这就是指针的出处,指针是一个特殊的变量,它用来储存地址
二、指针变量的声明和赋值
1、 指针变量的声明与对普通变量的声明基本一样,不同点就是在变量前加个 *
2、 指针变量的大小:32位机器为4字节,64为机器为8字节
3、 每个指针变量只能指向一种特殊类型 例如 int *p 、char *p、float *p....
4、 为了能找到变量地址、可以使用 &
5、 赋值 如下图所示
5、 * 运算符对指针变量也可以使用,且可以返回到原始变量,读取其值
三、二级指针
指针变量可以指向一个指针,即指向指针的指针
int a = 1;
int* p = &a; // 用p 存储变量 a 的地址 &为取地址符
int** p2 = &p; // p2 指向 p 的地址
四、指针与数组 和 指针的算术运算
1、数组名可以作为指向数组第一个元素的指针
2、指针可以加、减一个整数 例如:p + 1 可以访问 数组的第二个元素
3、指针可以减去指针
4、指针可以进行关系运算、比较大小
5、以上只有在同一数组中时,才有意义
下面演示2、3
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int i = 0;
int* p = arr;
for (i = 0; i <= &arr[9] - &arr[0]; i++) // &arr[9] - &arr[0] 输出9,代表两者中间元素个数
{
*(p + i) = i; // p + i 逐一访问数组元素 并把 i 的值替换数组元素
}
for (int j = 0; j < 10; j++) {
printf("%d\n", arr[j]); // 打印替换后的数组元素
}
return 0;
}
五、指针数组
整型数组——存储整型类型的数组
字符数组——储存字符类型的数组
指针数组——储存指针的数组
int main()
{
int arr1[5] = {1,2,3,4,5};
int arr2[5] = {2,2,3,4,5};
int arr3[5] = {3,2,3,4,5};
int *arrs[3] = { arr1, arr2, arr3 }; // 指针数组
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 5; j++) {
// printf("%d", *arrs[i] + j);
printf("%d", arrs[i][j]);
}
printf("\n");
}
}
六、数组指针
1、指向数组的指针
2、arr和&arr的区别
int main()
{
int arr[4] = { 1,2,3,4 };
int* p2 = arr; // p2 存的是数组首元素地址
int(*p)[4] = &arr; // p 存的是整个数组的地址 数组指针
// 但实际上p2 和 p 指向同一个地方
printf("%p\n", p2);// 000000705C1EF9A8
printf("%p\n", p2 + 1);// 000000705C1EF9AC
printf("%p\n", p); // 000000705C1EF9A8
printf("%p\n", p + 1);// 000000705C1EF9B8
// p2 和 p 的地址相同
// 可以看出 p2 + 1只跳过了4个字节,访问p2下一个元素
// 可以看出 p + 1跳过了16个字节,跳过了一个数组
}
七、函数指针和函数指针数组
函数指针:指向函数的指针、函数占用内存单元、每个函数也有地址、就像每个变量都有地址一样
函数指针数组:存放都是函数指针的数组
int main()
{
// 函数指针
int (*p)(int, int) = &add;
// 函数调用可以写出如下几种方式
// 函数名也可以算作地址
// Add === &Add
int a1 = add(2, 3);
int a2 = (*p)(2, 3);
int a3 = p(2, 3);
printf("%d\n", a1); // 5
printf("%d\n", a2); // 5
printf("%d\n", a3); // 5
// 函数指针数组-每个都是函数指针的数组
int (*p[3])(int, int) = { add, divide, multiply };
return 0;
}