文章目录
一、字符指针
1.指向一个字符
char ch = 'A';
char* pc = &ch;// *pc == ch;
2.指向字符串
(1)字符指针指向字符串首地址
将字符串赋给字符指针变量,字符指针变量存放的是字符串首字符的地址
int main()
{
char* ps = "Hello";
printf("%c", *ps);//打印结果为 H
return 0;
}
可以看出,将字符串"Hello"赋给字符型指针变量 ps,ps 存放的就是字符串首字符的地址,即 ps 指向’H’
(2)打印字符串
指向字符串的字符指针和数组名都表示字符串首字符地址
int main()
{
char* ps1 = "Hello";//字符指针 ps1 存放的是字符串首字符 H 的地址
char arr[] = "hello";//字符串存入 arr 数组里面
char* ps2 = arr;//字符指针 ps2 存放数组名,即首元素 h 地址
printf("%s\n", ps1);//打印结果为 Hello
printf("%s\n", arr);//打印结果为 hello
printf("%s\n", ps2);
//ps1 和 arr 都表示字符串首字符地址,都可以不用解引用打印出字符串,即打印首字母到'\0'的范围
return 0;
}
(3)字符指针和数组名的区别
#include<stdio.h>
int main()
{
char arr1[] = "Hello";
char arr2[] = "Hello";
char* ps1 = "Hello";
char* ps2 = "Hello";
if (arr1 == arr2)
printf("arr1 == arr2\n");
else
printf("arr1 != arr2\n");
if (ps1 == ps2)
printf("ps1 == ps2\n");
else
printf("ps1 != ps2\n");
return 0;
}
运行结果:
对数组来说,数组的创建会开辟出一块空间,用来存放数据,因此,数组arr1和arr2存放的字符串一样,但是数组的地址不一样,导致两个相同的首字符’H’在不同的地址
在C语言,对字符指针来说,两个字符指针变量 ps1 和 ps2 指向同一常量字符串,即,都指向这个字符串的首字符’H’
因此,arr1!=arr2,ps1==ps2
二、指针数组
就是数组,而数组元素为指针(地址)
例如:int* arr[10];
就是一个存放整型指针的数组
分析:下标引用操作符 [] 的优先级为 1,解引用运算符*
的优先级为 1;因此,先是 arr 与 [] 结合,代表 arr 是一个数组,然后与int*
结合,表示这个数组元素为指向整形数据的指针
1、指针数组的定义
#include<stdio.h>
int main()
{
int ar1[5] = { 1,2,3,4,5 };
int ar2[] = { 2,3,4,5,6 };
int ar3[] = { 3,4,5,6,7 };
int* arr[3] = { ar1,ar2,ar3 };//数组名即首元素地址
return 0;
}
就是将 3 个数组的首元素地址存到了一个int*
型的数组中
2、将这个指针数组打印出来
#include<stdio.h>
int main()
{
int ar1[5] = { 1,2,3,4,5 };
int ar2[] = { 2,3,4,5,6 };
int ar3[] = { 3,4,5,6,7 };
int* arr[3] = { ar1,ar2,ar3 };//数组名即首元素地址
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", *(arr[i] + j));
//(arr[i]+j)可以写成arr[i][j]
}
printf("\n");
}
return 0;
}
可以看出,这就相当于模拟实现了一个二维数组,不过这 3 个一维数组的地址并不连续
三、数组指针
就是指向数组的指针
1、数组指针的定义
//先创建一个数组 arr
int main()
{
int arr[5] = { 1,2,3,4,5 };
//arr表示首元素的地址,即arr[0]的地址
//&arr才表示数组arr的地址
return 0;
}
那么,如何创建一个指向数组arr的指针呢?
写成
int* parr[5]=&arr;(指针数组)
显然不行,这样就是一个指针数组
先是[ ]表示parr是存放5个元素的数组,然后*表示这个数组存放的是int型指针
正确写法应为:
int(*parr)[5] = &arr;
(数组指针)
先是 parr 与 * 结合,代表 arr 是一个指针,然后与 [] 结合,表示这个指针指向的是一个有5个元素的数组,最后,数组元素为 int 型
也就是,parr 指向包含 5 个 元素的int 型数组
注意,[]
的优先级比*
高;()与[ ] 优先级相同,根据结合律,从左向右运算
2、通过数组指针打印数组
#include<stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5 };
int(*parr)[5] = &arr;// &arr 即整个数组的首地址
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d\n", *(*parr + i));
//或者 printf("%d\n", (*parr)[i]);
}
return 0;
}
四、二维数组作为函数参数
1.形参为二维数组
/* 声明 */
void function(int a[m][n]);
void function(int a[][n]);//行数可以省略
/* 调用 */
function(arr);//数组名作实参
/* 访问元素 */
arr[i][j]
*(arr[i] + j)
*(*(arr+i) + j)
*((int *)arr +i*n +j )//n为列宽
2.形参为数组指针
/* 声明 */
void function(int (*a)[n]);
/* 调用 */
function(arr);//数组名作实参
/* 访问元素 */
arr[i][j]
*(arr[i] + j)
*(*(arr+i) + j)
*((int *)arr +i*n +j )//n为列宽
3.例子
void print1(int ar[][5], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf("%3d ", ar[i][j]);
}
printf("\n");
}
printf("\n");
}
void print2(int(*p)[5], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf("%3d ", *(*(p + i) + j));
}
printf("\n");
}
printf("\n");
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15} };
print1(arr, 3, 5);
print2(arr, 3, 5);
return 0;
}
运行结果: