携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情
2. 字符指针
能够指向字符数据的指针
形如这样的char* p
这里就讲比较难的地方吧!看下面这个代码
void pd(char* s1,char* s2)
{
if (s1 == s2)
printf("相等\n");
else
printf("不相等\n");
}
int main()
{
char arr1[] = "abcef";
char arr2[] = "abcef";
pd(arr1,arr2);
char* p1 = "abcef";
char* p2 = "abcef";
pd(p1,p2);
return 0;
}
这里的arr1和arr2,p1和p2相等吗?看结果
arr1与arr2不相等,p1和p2相等。在数组储存数据时,即使储存的字符串相等也开辟不同的空间。但是p1,p2可不能储存
"abcef"这样的常量字符串,它们只是储存了首字符的地址,所以p1和p2相等.并且p1,p2所指向内存的数据不能更改,因为初始化的常量字符串是不能更改的,可以这样写
const char* p1 = "abcef";
const char* p2 = "abcef";
3. 数组指针
数组指针本质上是指针,例如:
int (*p)[5]
*说明p是一个指针,指针指向一个数组,
数组中有5个元素,每个元素是int类型
这里的p的类型为 int (*)[5] 类型。
这样使用,例子:
void f(int (*p)[5],int n)
{
int i, j;
for (i=0;i<5;i++)
{
for (j=0;j<5;j++)
{
*(*(p + i) + j) = 1;
}
}
}
int main()
{
int arr[5][5]={1,2,3,4,5,6,7};
f(arr,5);
return 0;
}
- 这里的二维数组名表示第一行数组的地址,数组的地址要用数组指针进行接收。
下面这个对应着内存布局:
4. 指针数组
指针数组本质上是数组。例如:
int *p[5]
根据运算符的结合性可知,
p先与[]结合,说明p是一个数组,数组里面有5个元素,
每个元素是int*类型,也就是指针指向int类型
给个简单的例子: 看代码:简单
int main()
{
int arr1[] = { 1,2,3 };
int arr2[] = { 4,5,6 };
int arr3[] = { 7,8,9 };
int* p[] = { arr1,arr2,arr3 };
int i = 0, j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%d ", p[i][j]);
}
printf("\n");
}
return 0;
}
5.数组传参和指针传参
🥳1️⃣数组名表示的含义
- 一维数组名 一维数组名表示数组首元素地址
- 二维数组名 二维数组名表示首行数组的地址 每一行的数组都有自己的名字,对与下面的代码
arr2[0]为第一行数组的名字
sizeof(数组名)求的是整个数组的大小。
&数组名取出的是整个数组的地址
例子:看代码
int main()
{
int arr1[] = { 1,2,3,4,5,6 };
int arr2[][3] = { 1,2,3,4,5,6 };
printf("%d\n",sizeof(arr1));求的整个数组的大小,单位字节24
printf("%d\n", sizeof(arr2));求的整个数组的大小24
printf("%d\n\n", sizeof(arr2[0]));求的是第一行数组的大小12
printf("%p\n", arr1);首元素的地址
printf("%p\n", arr1+1);第2个元素的大小
printf("%p\n", &arr1);这个元素的大小
printf("%p\n\n", &arr1+1);越过整个数组后的地址
printf("%p\n", arr2);首行的地址
printf("%p\n", &arr2 + 1);越过这个数组后的地址
printf("%p\n", arr2[0]);首行首元素的地址
printf("%p\n", &arr2[0] + 1);第二行数组的首元素的地址
return 0;
}
- 运行的结果
🥳2️⃣数组传参
- 一维数组传参
f(int arr[])
{}
f(int arr[3])
{}
f(int* arr)
{}
上面这三种都可以,但是最后一种比较好,它能反应出数组名字为数组首元素地址,
像第1与第2种里面[]里面有没有数值的没有问题。
f1(int* arr1[])
{}
f1(int* arr1[3])
{}
上面这两种大家应该可以理解
f1(int** arr1)
{}
arr是数组名,表示首元素地址,每个元素是指针,即指针的地址要用二级指针接受
int main()
{
int arr[3] = { 1,2,3 };
int* arr1[3];
f(arr);
f1(arr1);
return 0;
}
对于一维数组传参,上面的几种都正确。
- 二维数组传参
f(int p[2][2] )
{}
f(int p[][2] )
{}
上面这两种都可以,也都可以理解,前一个数值可以省略,
但是第二个[]的数值不能去掉.
f(int(*p)[2] )
{}
二维数组名表示首行数组的地址,要用数组指针进行接收
int main()
{
int arr[2][2];
f(arr);
return 0;
}
🥳3️⃣指针传参
- 一级指针传参
f(int* p)
{}
int main()
{
int a = 0;
int* p = &a;
f(p);
return 0;
}
一级指针传参用一级指针进行接收
==思考==:形参为一级指针的时候,实参可以为什么样的类型 1️⃣实参可以为一维数组的数组名 2️⃣可以为一级指针
- 二级指针传参
f(int** p1)
{}
int main()
{
int a = 0;
int* p = &a;
int** p1 = &p;
f(p1);
return 0;
}
二级指针传参用二级指针进行接收
==思考==:形参为一级指针的时候,实参可以为什么样的类型 1️⃣实参可以为指针数组 2️⃣可以为二级指针 3️⃣可以为一级指针的地址