指针的相关解析和理解

C语言中的指针详解:从字符指针到函数指针
    • 字符指针

字符指针变量有两种表达方式,如图:

1 当变量为单个字符时,可以 直接char*指针变量名=&变量名

2 当变量为字符串时,可以char*指针变量名=“常量字符串”(这里的char*p="abcdef",相当于字符串首元素的地址a存放到字符指针p中,并不是整个字符串的地址都存放到p中。因此当打印%s时,是顺着字符串往下打印。

注:因为“abcdef”是常量字符串,是不会被改变的常量,所以最严谨的做法是:加const,避免下文出现修改。不加const,而下文出现修改,会异常。

例题1

解析:1, str1和str2是两个字符数组,所以内存里会分别创建两个空间,空间一是str1,空间二是str2,在空间一str1里放“hello bit",在空间二里放”hello bit“,内容相同,但是比较str1和sre2,是数组名,比较的也就是首元素地址,不同数组,不同空间的两个首元素地址不可能相同,所以not same

2 , str3和str4是两个字符指针,而”hello bit“是常量字符串,可以理解为str3和srt4指向的位置都是"hello bit"的首元素。意思就是,在c语言里,如果有多个指针指向同一个字符串时,实际上,这些指针指向的是同一个字符串。

    • 指针数组

类比其他数组:
整型数组---数组中存放整型
字符数组---数组中存放字符
指针数组---数组中存放指针(地址)

示例1:

当指针数组中放四个字符串,如图,就相当于"abcd","1234","efgh","ijkl"各自的首字符的地址,存放到了arr当中。

所以想调出指针数组中的每个指针元素,就可以利用循环。

示例2:

同理,存在arr中的四个元素,存的是各自数组里首元素的地址

所以,当想访问arr中的每个元素时,arr[0]=arr1=1的地址,arr[1]=arr2=0的地址,arr[2]=arr3=2的地址,arr[3]=arr4=6的地址,

所以,想通过arr来访问arr1里的所有元素,就可以通过循环:因为arr[0]=arr1 , arr1[j] , j=0,1,2,3,4, 所以1,arr[0][j] 这样子,就可以访问到arr1里的所有元素(arr2,arr3,arr4同理

也可以2, *(arr[0]+j ) ,arr[0]表示的是首元素地址,arr[0]+j, 表示下标为j的元素地址.然后解引用,就表示下标为j的元素

注:指针数组的类型
int *arr1[10]-----整型指针的数组
char*arr1[10]----一级字符指针的数组
char**arr2[10]----二级字符指针的数组

    • 数组指针

根据字符指针,整形指针

取地址数组名,放到指针pa里,指针指向的是arr,【10】=十个元素,int=元素是整型

所以,pa就是一个数组指针。

注:[]的优先级高于*,所以要加一个(),避免数组指针格式上写成指针数组

数组指针类型:int (*)[10] (打个比方,前面的类型和后面的数字可换)

pa=&arr (存地址 *pa=*&arr(解引用 *pa=arr(本质

数组名和&数组名的区别

如图,发现arr &arr[0] &arr打印出来的地址都是0113fc24,但是只要+1(+1跳过多少,跟指针类型有关,首元素地址是int* 跳过的就是4个字节),数据就会发生变化。

十六进制:1 2 3 4 5 6 7 8 9 a b c d e f

arr---arr+1=8c---90=4

&arr[0]---&arr[0]+1=8c---90=4

&arr---&arr+1=8c---b4=40

arr的指针类型是int* arr[0]的指针类型也是int*,但是&arr的指针类型是int(*)[10] 、

arr是数组首元素的地址 &arr是整个数组的地址

首元素的地址和数组的地址,值相同,但意义不同

注:&arr取出的是整个数组的地址,只有数组的地址才需要指针数组来接收

数组指针的用法

正经打印一个一维数组:

不正经的打印一个一维数组

很合理,但没必要

正经打印一个二维数组

加入数组指针的打印一个二维数组

解析:

print2(arr,3,4) 数组传参,指针接收。 传的是数组首元素的地址,而对于二维数组来说,

首元素 第二个元素 第三个

所以传过去的是{1,2,3,4}这一整个的地址,长得很像一个没取名的数组,形式上是一个一维数组。所以把一整个数组的地址进行传参,那么就要用 数组指针 进行接收,而数组里有4个元素,元素类型是int。格式就是---int(*p)[4]

p接收的是一行(也就是arr中的一个元素),所以p+1跳过的就是一行,

p+i,i=0 1 2 ,对应的就是三行的地址,所以*(p+i)相当于是拿到了对应行数的元素,(相当于是一维数组已知数组名),( *(p+i) ) [j] 就是行里的每一个元素(相当于数组名[j])

当然,*(p+i)[j]也可以换成p[i][j]

(数组传参,传给p的是三个地址,对于p来说是有三个元素,而每个元素下有四个小元素,总而言之,就是二维数组)

示例:

int arr[5]------整形指针,元素是5个

int*p[5]------指针数组,数组元素是5个,每个元素的类型是指针

int(*p)[5]-----p是数组指针,指向的数组元素是5个,每个元素的类型是int

int(*p[10])[5]-----p[10]是数组,元素是10个。 外面的部分分离出来就是int (* )[5]属于数组指针,指向的数组元素是5个,每个元素的类型是int

    • 数组传参

一维数组传参类型

二维数组传参类型

一级指针传参

一级指针传参,一级指针接收

一级数组接收,传参可以有哪些类型

void test(int*p)

{}

int a=10;

int*p=&a;

int arr[5]={1,2,3,4,5};

test(&a)//整型变量

test(arr)//整型数组

test(p)//一级指针

二级指针传参

二级指针传参,二级指针接收

当函数的参数是二级指针,可以接收的是什么参数

void test(int**p)

{}

int**p;

int*ptr;

int *arr[5];

test(p);//二级指针变量

test(&ptr);//一级指针地址

test(arr);//指针数组的数组名

    • 函数指针

指向函数的指针

函数指针典例

1.

理解代码:函数的调用,调用0处地址的一个函数,无参

2.

函数的声明

signal的返回类型是函数指针,意思就是,在调用完signal之后,返回的是一个函数地址

因为这样很难,所以可以自定义一下(typedef)

typedef unsigned int uit 。 unsigned int是原来的类型名,uit是重命名之后的名字

我们可以

结束。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值