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

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是重命名之后的名字
我们可以

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

被折叠的 条评论
为什么被折叠?



