目录
前言:
对于指针已知的知识点
1.指针是一种变量,即是用来存放一个最小内存单元(一个字节大小)的唯一地址,来标识这个存储空间,如一栋酒店里面每个房间的房间号。
2.指针的大小根据电脑的决定其大小,64位是8个字节,32位是4个字节。
3.指针的类型决定了
a.指针加减整数时的步长。如一个int* 类型的指针+1,就将在内存存储中移动四个字节;
b.指针在解引用操作时,其能访问内存的空间大小的权限。如一个char* 类型的指针解引用时只会访问一个字节的内存空间
4.指针的运算. 如指针加减整数;指针加减指针。
1、字符指针
char ch = 'a';
char* pa = &a;
*pa = 'b';
字符指针指向单个字符的创建、解引用的操作
const char* p = "woshixiaoba001";
*p = 'x' //error
字符指针指向一个常量字符串,
首先p存储的是字符串首字符的地址,而不是整个字符串的全部信息。因为常量字符串是常量不可以改变,所以对其指针解引用后想重新赋值是不行的。
小练习:
因为str1 与str2是两个不同的字符数组(根据数组名,判断而不是数组中存放的内容),在创建数组时会各自在内存中开辟空间。因为数组名即首元素的地址,所以str1与str2不同。
因为“woshixiaoba001”是常量字符串,是单独存放在内存中的。将其首元素地址存入了两个不同名字的char*类型的指针,所以str3与str4两个指针中的地址都是字符串首元素地址,即字符‘w’的地址。因为是常量字符串,其内容是不能改变的,加上const增加鲁棒性。
2、指针数组
指针数组是数组,数组中元素的类型是指针。
int arr[8]; //整型数组
char* arr[10];//一级指针数组
double** arr[12];//二级指针数组
小应用1:通过字符指针存储一系列的字符串信息
小应用2:模拟创建二维数组
在使用时可以写成二维数组的下标形式,也可以写成对指针解引用的形式。
3、数组指针
3.1 数组指针定义
数组指针是指针,是指向数组类型的指针。
char* pch //字符指针
int* pint //整型指针
float* pfloat //浮点型指针
int (*parr)[10] //数组指针
int *parr[10] //指针数组
如在创建数组指针int (*parr)[10] 时,必须要用()将解引用操作符*与指针变量名括在一起,表示这是一个指针变量,因为解引用操作符*与下标引用操作符[ ]相比前者优先级较低。然后[ ]表示这个指针是指向的是数组类型,数组中每个元素的类型为int.
3.2 数组名与&数组名
数组名一般默认为数组首元素的地址,如整型数组数组名对应的是整型指针变量,其类型是整型指针。若对其加减整数1,其偏移量在内存中是4个字节;对其解引用,则访问的是4个字节内存单元。
数组名只有两种情况表示整个数组
1、sizeof(单独存在数组名)-计算的是整个数组的大小,单位为字节。
2、&数组名-取出的是整个数组的地址。此时取出来的是一个数组指针变量,对应的类型是数组指针。若对其加减整数1,其偏移量是整个数组在内存中存储的字节大小;若对其解引用得到的是数组名,也就是首元素地址,类型又转换为数组元素对应的类型。
3.3 数组指针的使用
//一维数组 数组形式传参;
void print1(int arr[10], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//一维数组 指针形式传参(首元素地址,是指针类型跟元素的类型有关);
void print1(int *arr, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(arr+i));
}
printf("\n");
}
//一维数组 指针形式传参(数组指针);
void print2(int(*p)[10], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", (*p)[i]);//arr;
}
printf("\n");
}
在一维数组中,数组指针传参使用较少,一般都以前两种形式居多。
//二维数组 数组形式传参
void print3(int arr[3][5], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
//二维数组 数组指针形式传参
void print4(int (*p)[5], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ", *(*(p + i) + j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
print_arr1(arr, 3, 5);
//数组名arr,表示首元素的地址
//但是二维数组的首元素是二维数组的第一行
//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
//可以数组指针来接收
print_arr2(arr, 3, 5);
return 0;
}
数组指针在二维数组传参时很好用!
小练习:
int arr[5]; 这是整型数组;
int *parr1[10]; 这是整型指针数组;
int (*parr2)[10]; 这是整型数组指针;
int (*parr3[10])[5]; 这是整型数组指针数组
4. 数组参数、指针参数如何传参
4.1一维数组传参
#include <stdio.h>
void test(int arr[])// √ 数组形式传参
{}
void test(int arr[10])// √ 数组形式传参,下标引用为任何数都可以,不影响;
{}
void test(int *arr)// √ 指针形式传参,传递首元素的地址
{}
void test2(int *arr2[20])// √ 数组形式传参
{}
void test2(int **arr2)// √ 指针形式传参,因为是整型指针数组,所以首元素地址是一个二级指针。
{}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
}
4.2 二维数组传参
void test(int arr[3][5])// √
{}
void test(int arr[][])// ×
{}
void test(int arr[][5])// √
{}
//总结:二维数组数组形式传参,函数形参的设计只能省略第一个