C语言指针学习——指针知识巩固以及与函数、数组、结构体的关系

看了一个教程,进一步学习了C语言的指针,参考的教程已经找不到出处了(侵删)

从名字开始,按符号的优先级进行结合

名字:
“整型变量” —— int a; 这种
“(指向)整型指针”—— int *p; 这种,指向整型变量
“整型数组”——int a[5]; 这种,数组元素都是整型变量

符号结合的优先级:
表示是数组的 [ ] > 表示是指针的* ;
表示是函数的()> 表示是指针的 *;

1. int p;
定义了一个整型的变量p

2. int *p;
从名字开始看,名字是p;
先和*结合 —— 表示p是指针;
再和int结合 —— 表示指针指向整型。
**p是一个指向整型变量的指针即“整型指针”**

3. int p[5];
从名字开始看,名字是p;
先和[]结合 —— p是数组;
再和int结合 —— 数组元素是整型。
**p是一个由整型变量组成的数组(整型数组)**

4. int *p[2];
从名字开始看,名字是p;
先和[]结合 —— p是一个数组;
再和*结合 —— 数组元素是指针类型;
再和int结合 —— 指针指向整型(整型指针);
**p是一个由(指向)整型(的)指针变量组成的数组**

5. int (*p)[2];
从名字来看,名字是p;
先和*结合 —— p是一个指针;
再和[]结合 —— 指针指向数组;
再和int结合 —— 数组元素都是整型;
**p是一个指向整形数组的指针**

6. int **p;
从名字来看,名字是p;
先和一个*结合 —— p是一个指针;
再和另一个*结合 —— 指针指向指针;
再和int结合 —— 被指向的这个指针是指向整型的指针(整型指针);
**p是一个指向整型指针的指针(二级指针)**

7. int p(int);
从名字来看,名字是p;
先和表示函数的(int)结合 —— p是一个函数;
进入()int ——函数需要一个int型参数;
再和外面的int结合 —— 函数的返回值是一个整型量;
p是一个“需要整型作为参数,返回值是整型量”的函数

8. int (*p)(int);
从名字来看,名字是p;
先和*结合 —— p是一个指针;
再和表示函数的(int)结合 —— 指针指向函数;
进入()int —— 函数需要一个int型参数;
再和外面的int结合 —— 函数的返回值是整型;
p是一个指向“需要整型作为参数,返回值是整型量的函数”的指针

9. int *p(int);
从名字来看,名字是p;
先和(int)结合 —— p是一个函数;
再和*结合 —— 函数的返回值是一个指针;
再和int结合  —— 指针指向整型量;
**p是一个“需要整型作为参数,返回值是指向整型的指针”的函数**

10. int p(int)[2];
从名字来看,名字是p;
先和(int)结合 —— p是一个函数;
再和[]结合 —— 函数返回值是数组;
再和int结合 —— 数组元素是整型;
p是一个“参数是整型,返回值是整型数组”的函数

11. int (*p(int))[2];
从名字来看,名字是p;
先和(int)结合 —— p是一个函数;
再和*结合 —— 函数返回值是指针;
再和[]结合 —— 指针指向数组;
再和外面的int结合 —— 数组元素是整型;
**p是一个“需要整型作为参数,返回值是指向整型数组的指针”的函数**

12. int *(*p)[2];
从名字来看,名字是p;
先和*结合 ——p是一个指针;
再和[2]结合 —— 指针指向数组;
再和*结合 —— 数组元素是指针类型;
再和int结合 —— 指针指向整型(即数组元素是整型指针);
p是一个指向 “ 由整型指针变量构成  的数组 ” 的指针
 
 12. int *(*p(int))[2];
 从名字来看,名字是p;
 先和(int)结合 —— p是一个函数;
 再和*结合 —— 函数返回值是指针;
 再和[]结合 —— 指针指向数组;
 再和外面*结合 —— 数组元素是指针变量;
 再和外侧int结合 —— 指针指向整型变量;
 p是一个“参数是整型,返回值是指向  由整型指针变量构成的数组  的指针”的函数

```c

指针和内存:
指针自身的值——是地址,表示的是内存区域;
指针指向的值——是这个地址(内存区域)上存的数据;

指针所指向的内存区域就是从指针所代表的的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片区域。

我们说一个指针值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;
我们说一个指针指向了某块区域,就相当于说该指针的值是这个内存区域的首地址。

指针本身所占据的内存区:
在32位平台里,指针本身占据了4个字节

指针的算数运算:
指针可以加上或减去一个整数——是以单元为单位进行的加减
两个指针不能进行加法运算;
两个指针可以进行减法,但必须类型相同(一般用在数组方面);

char a[20]="You_are_a_girl";
char *p=a;
char **ptr=&p;
printf("**ptr=c%\n",**ptr);
ptr++;
printf("**ptr=c%\n",**ptr);

分析:
p是指向char的指针;   ptr是二级指针,指向的是一个指针;
当p+1时,内存地址移动的是size(char)=1个字节的位置,
刚好一到a[1]的地址上;当ptr+1时,内存地址移动的是size(p)=4个字节的位置,
但是!这是ptr移动了四个字节的位置,鬼知道移动到哪了(要是是p移动4个字节
的位置,那就是到了a[3]的位置了),所以说,实际上是跑飞了 ——  
二级指针移动容易跑飞

总结:
一个指针ptrold 加(减去)一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加(减少) n * sizeof(ptrold所指向的类型)个字节!!!—— 移动了n个他所指向的类型的空间——像数组那样移动和访问

运算:*、&

*p的结果就是p所指向的东西:
他的类型是p指向的类型,他占用的地址是p所指向的地址

int a=12,b;//整型
int *p;//指针变量
int **ptr;//二级指针

p=&a;//p是指针变量,取出a的地址然后赋值给p
*p=24;//*p表示p指向的值——a,相当于把a赋值为24
ptr=&p;//左边是二级指针,右边是取出指针的地址

*ptr=&b;
//*ptr表示ptr指向的类型——即一级指针p,左边是一级指针,右边是一级地址
**ptr=34;
//**ptr:二级指针取两次地址就成了对应的数据类型——int型,右边是整型34


数组和指针
数组的数组名可以看做一个指针

char *str[3]={ "hello", "goodmorning", "world"};
//str先与[]结合——是数组;再与*结合——数组元素是指针类型;
//再与char结合——是char型指针;str是一个“由char型指针组成的”数组

//而字符串相当于是一个数组,在内存中以数组的形式储存,只不过字符串是一个
//数组常量,内容不可更改。如果看成指针的话,他是常量指针,也是指针常量

//数组元素是指针,那么数组名显然就要成为了二级指针 —— 指向指针
str[0]=*str;//str是二级指针,*str表示str所指向的那个指针
str[1]=*(str+1);//1移动的就是1个 char* 类型的长度 —— 移动1个所指类型
str[2]=*(str+2);//2移动的就是2个 char* 类型的长度 —— 移动2个所指类型

str+1是一个二级指针,指向数组的第1号单元,"goodmorning"的地址
*(str+1)是一个一级指针,指向"goodmorning"的第一个字符"g"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值