先复习复习(点击进入) -> 指针基础
先把握以下几个概念:
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间
- 指针的大小是固定的,32位平台位4个字节大小,64位平台位8个字节大小
- 指针有类型,指针的类型决定了指针+或者-整数的步长,指针解引用操作的时候的权限
- int a = 10;
int *pa = &a;
p的值为 a的地址
*p的值为 p所指向空间的值,即 *p= 10
&p的值为指针变量 p的地址
字符指针
字符指针就是指向字符的指针:char*;
一般使用
void main()
{
char ch = 'a';
char* pch = &ch;
*pch = 'w'; //修改字符ch的值为w
}
(字符串)区分字符数组与字符指针
观察以下两种定义方式:
char str1[] = “abcd”;
char *str2 = “abcd”;
上面定义str1与受str2都可以称为“字符串”,但是两者却有着本质的区别:
- char str1[] = “abcd”;
- 应该称str1为一个字符数组
- 运行可知sizeof(str1) 的值为5
- 本质是开辟了一块大小为5字节的内存空间,该内存空间的名字为str1,空间内存放’a’, ‘b’, ‘c’, ‘d’, ‘\0’
- char *str2 = “abcd”;
- 应该称str2为字符指针
- 运行可知sizeof(str2) 的值为4(32位平台)
- 本质是将“abcd”的首字符的地址放入了str2中,“abcd”是一个常量字符串,不能通过指针去修改其值
下面,请仔细观察下面代码:
void main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
char* str3 = "hello bit.";
char* str4 = "hello bit.";
if (str1 == str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if (str3 == str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
}
该代码的输出结果是:
str1 and str2 are not same
str3 and str4 are same
出现这个结构的原因如下:
str1与str2都是字符数组,只是用相同的常量字符串进行了初始化,但是两者所开辟的内存块不同;
str3与str4都是字符指针,两者指向的是同一个常量字符串,C语言/C++会将常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们是机会指向同一块内存。
指针数组
指针数组 – 是数组,是存放指针的数组
int *arr1[10]; //存放整型指针的数组
char *arr2[4]; //存放字符指针的数组
char **arr3[5]; //存放二级字符指针的数组
数组指针
数组指针 – 是指针,是指向数组的指针
指针数组 与 数组指针 的区分
- int *arr1[10]; //指针数组
- int (*arr2)[10]; //数组指针
可以看出arr1与arr2的区别就是一对小括号 () ;
那如何理解呢?
- [] 的优先级是高于 * 的,所以在没有 () 时,名字会先与 [] 结合,所以其大前提就是一个数组;
- 而加了 () 之后,名字会先与 * 结合,所以其大前提就是一个指针。
&数组名 与 数组名 的区分
先看一段代码:
void main()
{
int arr[] = { 1,2,3,4 };
printf("%p\n", arr);
printf("%p\n", &arr);
}
通过运行可以发现,&arr与arr打印出来的值是一样的,都是首元素的地址。但是两者的含义一样吗?
当然不一样!
为了验证两者是不同的,先来看下面一段代码:
void main()
{
int arr[] = { 1,2,3,4 };
printf("arr: %p\n", arr);
printf("arr+1: %p\n", arr + 1);
printf("&arr: %p\n", &arr);
printf("&arr+1: %p\n", &arr + 1);
printf("%d", sizeof(arr));
}
运行之后发现,arr+1只增加了4个字节,而&arr+1增加了16(十六进制的10是十进制的16)个字节。
arr与&arr的值虽然一样,但是含义不一样
- arr的值是数组首元素的地址,arr+1就是数组第二个元素的地址
- &arr标识的是整个数组的地址,&arr+1,也就是数组的地址+1,跳过整个数组的大小,数组的大小为16,所以&arr+1相对于&arr的差值为16.
数组指针的使用
- 既然数组指针是指向数组的指针,那么指针中存放的应该是数组的地址
代码示例:
void main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
int(*parr)[10] = &arr; //把数组arr的地址赋值给指针变量parr
}
- 一个数组指针的使用代码示例:
void print_arr1(int arr[][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print_arr2(int (*parr)[3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
}
void main()
{
int arr[5][3] = { 1,2,3,4,5,6,7,8,9,10 };
print_arr1(arr, 5, 3);
printf("\n---------------\n");
print_arr2(arr, 5, 3);
}
- 对于二维数组 arr[5][3] 来说,可以认为其每一个元素都是一个有三个元素的一维数组(arr[3]),这个二维数组一共有5个这样的一维数组。
- 数组名表示的是首元素的地址,所以在函数print_arr2中,可以用数组指针来接收二维数组的名字arr。
小总结
最后,来看看下面代码的含义吧:
int arr[5]; //整型数组
int *parr1[10]; //指针数组
int (*parr2)[10]; //数组指针int (*parr3[10]) [5]; //数组指针数组
是一个数组,该数组存放的是指针,存放的指针指向的是整型数组