1.前言-指针的概念
(1). 指针是变量,用来存放地址,地址唯一标识一块内存空间。
(2). 指针大小是固定的 4/8 个字节(32位平台/64位平台)。
(3). 指针是有类型的,决定了指针的 +- 整数的步长,指针解引用操作时的权限。
(4). 指针的运算。
2. 字符指针
//char*
char ch = 'w';
//ch = 'a';
char* pc = 'w';//pc为字符指针
*pc = 'a';
再看这种形式:
char arr[] = "abcdef"; //字符数组中存放[a b c d e f \0]
const char* pc = "abcdef"; //"abcdef"是常量字符串,首字母a的地址放在pc中,pc的类型是char*
3. 指针数组
指针数组是一个存放指针的数组
//整形数组 - 存放整形的数组
//字符数组 - 存放字符的数组
//指针数组 - 存放指针的数组
int arr1[10]; //存放整形的数组
int* arr2[10]; //存放整形指针的数组 - 整形指针数组
char* arr3[10]; //字符指针数组
char** arr4[10]; //二级字符指针数组
使用指针数组模拟实现二维数组
#include
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[] = { 2, 3, 4, 5, 6 };
int arr3[] = { 3, 4, 5, 6, 7 };
int* arr[3] = { arr1, arr2, arr3 };//指针数组
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
4. 数组指针
数组指针本质是指针
int* num1; //指向整形变量的指针,存放整形变量地址的指针变量
float* num2; //指向浮点型变量的指针
char* ch1; //指向字符型变量的指针
int *p1[10]; //指针数组
int (*p2)[10]; //数组指针,指向数组的指针,存放的是数组地址的指针变量
//p2是数组指针变量,指向int [10]数组
&数组名与数组名
//数组名是数组首元素的地址
//数组名表示首元素地址有两个例外
//1. sizeof(数组名),这里的数组不是首元素的地址,数组名表示整个数组。
//sizeof(数组名)计算的是整个数组的大小。单位是字节。
//2. &数组名,这里的数组名仍然表示整个数组,取出的是整个数组的地址
//除此之外,所有的地方数组名都是数组首元素的地址
int main()
{
int arr[10] = { 0 };
printf("%p\n",arr);//int*
printf("%p\n", arr+1);
printf("%p\n", &arr[0]);//int*
printf("%p\n", &arr[0]+1);
printf("%p\n",&arr);//int(*)[10]
printf("%p\n", &arr + 1);//跳过整个数组
//printf("%d\n", sizeof(arr));
return 0;
}
通过调试发现&arr[0],与&arr类型不同,但指向的都是首元素的地址
且arr+1与arr[0]+1都是跳过4个字节,而&arr+1跳过整个数组
因此数组指针的写法为:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//数组的地址,存放到数组指针变量,类型:int (*)[10]
//int[10] * p = &arr;//error
数组指针的使用:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
/* int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}*/
int(*p)[10] = &arr;//数组的地址,存放到数组指针变量,类型:int (*)[10]
int i = 0;
for (i = 0; i < 10; ++i)
{
printf("%d ",(*p)[i]);//*&arr-->arr;
//printf("%d ", *((*p) + i));
}
return 0;
}
上述代码利用数组指针后反而变得复杂了,那么数组指针如何正确使用呢?一般在二维数组使用中比较方便。代码如下:
void Print(int(*p)[5], int r, int c)//int(*p)[5]-二维数组第一行
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ", *(*(p + i) + j)); //p->第一行
//printf("%d ",p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7 };
//二维数组首元素地址是第一行的地址
//一维数组的地址-数组的地址
Print(arr,3,5);
return 0;
}
5. 函数指针
首先看一段代码:
//数组指针 - 指向数组的指针
//函数指针 - 指向函数的指针
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("%p\n", Add);
printf("%p\n", &Add);
//函数名是函数的地址
//&函数名也是函数的地址
int(*pf)(int, int) = &Add;
//int(*pf)(int, int) = Add;
//int(*)(int,int)是函数指针类型
int ret1 = Add(3,5);
printf("%d\n", ret1);
int ret2 = (*pf)(3, 5);
printf("%d\n", ret2);
int ret3 = pf(3, 5);
printf("%d\n", ret3);
return 0;
}
运行结果: