各位帅哥靓女们,我是猪猪,这期给大家带来的是指针的进阶解析,也就是带带大家看看更多的关于指针的内容,老规矩,如果猪猪有哪里说的不对的地方还请于评论区斧正,如果觉得猪猪讲的还可以的话,还请给猪猪一键三连,毕竟猪猪码字不易。
【一】指针内容的回顾
1.指针是什么?
指针就是一个变量,从来存放地址,地址是标识一块空间的唯一标识。
2.指针的大小?
指针的大小是固定的,取决你的电脑的平台,如果你是32位平台则为4字节,如果你是64字节你就是8字节。
3.指针的类型的作用
指针的类型决定了这个指针的访问权限的问题,char*类型访问接下来的一个字节的内容,int*类型访问接下来的四个类型的内容,以及指针加一之后所移动的空间大小,如果char*类型的指针,就往后面移动一个字节的空间,如果是int*类型的指针就是往后面移动四个字节的空间。
【二】字符指针类型
在指针的类型中我们知道有一种类型叫做char*;
往往我们是这么使用的:
int main()
{
char* p="abcdef";
char*pc=&p;
*pc='w';
return 0;
}
从我们的视角来看很容易将这个认为成将abcdef放入到指针p里面了,但是你想想一个指针类型才是四,但是abcdef是六个字符了,这都六个字节了,不可能放的下的啊,所以存放的方式肯定不是我们想的那样,其实本质上是将首地址放入到了p类型的变量中。相信这个大家是非常好理解的,那么就看下面一段代码:
#include<stdio.h>
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const 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");
return 0;
}
很多同学都觉得这个程序输出的结构肯定两个都是两个是不相同的,因为代码创建了不同的变量,导致地址是不一样的,所以后面比较的时候肯定是不一样的。但是输出的结果是:
这是为啥呢?因为c/c++会把常量字符串存放到一个单独的内存区域,当几个指针指向的内容是相同的时候,他们会指向相同的一块内存,但是用相同的常量字符串的去初始化不同的数组的时候就会开辟出不同的内存(只读区)。这个时候有细心的小伙伴就要问了,常量字符串?这个字符串是常量?对,同学你说的没错,这个字符串就是常量,是修改不了的,不信你去试试。
【三】指针数组
在浅析指针中我们提到过指针数组,指针数组就是一个存放指针的数组,例如:
char* arr1[3] char* arr2[4] char* arr3[5]
【四】数组指针
数组指针的是指针,指向的是一个数组,那么看接下来的一段代码:
int *p1[10];
int (*p2)[10];
[]的优先级高,所以p1先和数组结合,在和*结合,所以第一个就是指针数组,本质p是
一个数组,数组大小为10,里面存放的是int* 的内容。
p先和*结合说明p是一个指针,指向是一个大小为10的数组。
【五】&数组名vs数组名
看下面一段代码:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0; }
结果:
从结果可以看出来,虽然&arr和arr的值是相同的,但是两者包含的意义确实完全不相同的,
arr+1只是从arr[0]的位置移向了arr[1]的位置
&arr+1的位置是向后跳过了一个数组,也就意味&arr+1的类型是int (*)[10],即为指针数组的类型,所以+1跳过的就是一个数组的类型。
【五】数组指针的使用
我们都知道了数组指针的概念,那么数组指针是咋用的呢?来人上代码:
#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col) {
int i = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print_arr2(int (*arr)[5], int row, int col) {
int i = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
print_arr2(arr, 3, 5);
return 0; }
结果都是相同的,但是为啥呢?
第一种方式使用的是二维数组接受这个这个二维数组,你会发现接口刚刚好,所以按照二维数组的访问方式一点问题没有。
第二种方式就是数组指针的方式,也就是接受者为数组指针,且指针指向的数组大小和二维数组的一行所含有的大小是一样的,这个时候就可以挨个访问行,然后访问行里面的列的数据了。
【六】函数指针
首先大家一起看一段代码:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0; }
有的小伙伴就要问了,乖乖函数也会有地址?然而事实就是,在c语言中,只要你有空间你就会有地址,所以函数是需要开辟空间的,这样自然就会有地址了。
那么函数地址是如何保存在地址之间的呢?例如
我定义一个函数为void text,那么函数的指针就定义为:void(*p)()=&text;
也就是定义为: 返回值类型(*指针名)(参数类型)=&函数
应用起来也是非常好应用的,因为函数名就是地址名,而我指针指向的空间也是地址,所以你可以理解成将函数换了一个名字而已。
以上就是这期猪猪所有的内容了,如果觉得猪猪讲的还不错的话,还请给个一键三连,毕竟猪猪码字不易。