指针的学习

一维数组:

int a[10];

int *p=&a[0]           p=&a[0]          *p=a[0]


p+1->&a[0]+1         //指针加1在数值上表示加了1个指向类型的长度sizeof(int)

p+1->&a[0]+1->&a[1]                  以此类推

p+2->&a[0]+2->&a[2]

.......................................

p+i->&a[0]+i->&a[i]

在一个数组中,如果定义了一个指针保存a[0]的地址,则有式子 p+i->&a[0]+i->&a[i]

*(p+i)->*(&a[0]+i)->*(&a[i])->a[i]


1、在以上条件的基础上,假如要把100的值赋给a[0],请问有几种方法?

a[0]=100  <->  *(&a[0])=100  <->  *p=100  <->  *a=100  <->  *(p+0)=100  <->  p[0]=100

2、假如int a[10],int *p=&a[2],请问p[2]表示:

p->&a[2]  -->  p[2]  <->  *(&p[2])  <->  *(&p[0]+2)  <->  *(p+2)  <->  *(&a[2]+2)  <->  *(&a[4])

a[2]  <->  *(&a[2])  <->  *(&a[0]+2)  <->  *(a+2)  <->  a[2]


int a[10]        int *p=a  <->  int *p=&a[0]  ==>  p=a  ==>  p=&a[0]

数组名可以代表数组的首元素地址  a  <->  &a[0]

sizeof(a):求整个数组的大小

typeof(a):求这个数组的类型

typeof(p)  <->  typeof(&a[0])  <->  typeof(a[0])*  <->  int  *  ===>   typeof(&x)  <->  typeof(x)*

p=a:都是保存了a[0]的地址

a+1:&a[0]+1==>&a[1]     //这个时候把数组名当做指针来用

*(a+1):*(&a[0]+1)==>*(&a[1])==>a[1]           //这个时候把数组名当做指针来用


int a[10]={1,2,3,4,5,6,7,8,9,10}       

int a[10] <==>  int[10]  a  <==>  typeof(a) ==> int [10]

a:&a[0]

a+1:&a[0]+1  <==>  &a[1]

&a+1:a是数组,&a表示的是数组的指针,指针做加减,要观察指针的类型===>&a                        typeof(&a)  ==>  typeof(a)*  ==>  (int [10])*  ==>  表示每次指针加减都是在10个int类型的基础上进行!       &a+1  ==>  加10个int大小的字节

&a[0]+1:typeof(&a[0])  ==>  typeof(a[0])*  ==>  int *  ==>指针每次加减是在一个int字节的基础上

注意:  

a:&a[0]  数组首元素地址

&a[0]:取数组的第一个元素的地址

&a:取整个数组的地址,这是一个指向数组的地址

typeof(&a)  <==>  typeof(a)*  <==>  (int[10])*:指针每次加减是在10个int大小字节的基础上进行

typeof(&a[0])  <==>  typeof(a[0])*  <==>  int*:指针每次加减都是在1个int大小字节的基础上进行


二维数组:

int b[2][3]={1,2,3,4,5,6}           

二维数组本质是一个一维数组:int b[2][3] ==>(int[3]) b[2]

b:数组名做数组首元素地址 ==> &b[0]

&b:这里把b看做整个数组

&b+1:指针做加减看类型==>  typeof(&b)  ==>  typeof(b)*  ==>  (int[2][3])* :指针加减都是在一整个二维数组大小的字节数的基础上  

b+1:&b[0]+1  指针加减看类型:typeof(&b[0]) ==> typeof(b[0])*  ==>int[3]*    指针每次加减在一个3个int大小的字节的基础上            b+1 ==>  &b[0]+1 ==> &b[1]

&b[0]+1:typeof(&b[0]) ==>  typeof(b[0])*  ==>  (int[3])*      &b[0]+1==>&b[1]


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

int *ptr=(int*)(&a+1)

分析:typeof(&a)==>typeof(a)*==>(int[5])*:指针每次加减都是加减整个数组5个int字节大小          强制类型转换成(int*),变成指针每次加减一个int字节大小       

*(a+1):*(&a[0]+1)  指针加减看类型,typeof(&a[0])=typeof(a[0])*=int*:指针每次加减一个int字节大小,所以*(&a[0]+1)=*(&a[1])=a[1]

*(ptr-1):ptr本来是(&a+1),数组的首地址往后移动了5个int字节大小,强制转换成int*类型,指针每次加减1个int字节大小,ptr-1往前移动一个int字节,所以是a[4]=5;


在上面二维数组的基础上,要定义一个指针变量p,保存数组的第一个数值b[0][0]的地址,该如何定义呢?

typeof(b[0][0])=int*   ==>   所以可以这样定义p ===>int *p=&b[0][0]

二维数组名b代表的意思有:&b[0],如果要用指针p保存这个地址的话,应该怎么去写呢?

typeof(b[0]) == (int[3])*  ===> 所以可以这样定义p的类型 ===> (int[3])* p=&b[0]=b ===> 因为类型和数字不能连在一起===>int (*p) [3]=&b[0]=b ==>这样也叫数组指针 


数组指针:

数组指针归根结底是指针,指向一个数组,用来保存数组的地址;

像上面部分写的那样,int (*p) [3]=&b[0]=b,

指针数组:

指针数组是一个数组,数组里面的每个元素是指针;

int* p[3]:定义一个数组p,里面有3个int*,3个int类型的指针;

区别:

数组指针:int (*p)[3]

指针数组:int *p[3]

注意:要避免访问未初始化的指针!


定义一个二维数组int a[3][4]  ==>  (int [4] a[3]);  

表达式类型含义
a+iint [4]第i行的首地址&a[i]
*(a+i)+jint*第i行第j列的元素的地址
*(*(a+i)+j)int第i行第j列的元素
表达式表达式的值表达式的含义
a

表示数组名

sizeof(a)、typeof(a)代表整个数组

&a代表一个指针

数组的首元素地址&a[0]

a[0]

表示数组名

sizeof(a[0])、typeof(a[0])代表整个数组

&a[0]代表一个指针

表示数组第一行第一个元素的地址
a[0][0]表示数组元素表示数组第一行第一列的元素
a+1a是指针,&a[0]+1=&a[1]数组第二行的首元素地址
&a+1typeof(&a) ---> int [3][4] *,&a+1:指向下一个数组a类型元素的首地址(加了一整个数组a的大小)
 a[1]+2&a[1][0]+2 &a[1][2]
 *(a+1)+2 *(&a[0]+1)+2==>*(&a[1])+2===>a[1]+2===> &a[1][0]+2 ==>&a[1][2]
 
*(a[1]+2)*(&a[1][0]+2)==>*(&a[1][2])==> a[1][2]
*(*(a+1)+2)*(*(&a[0]+1)+2)==>*(a[1]+2)==>*(&a[1][0]+2)==>a[1][2]
  • 第二个:*(a+i)+j,可以表示为*(&a[0]+i)+j,可以表示为*(&a[i])+j ==>a[i]+j,a[i]这里是一个一维数组,在这里当指针使用,a[i]+j ==> &a[i][0]+j ==> &a[i][j],所以typeof(&a[i][j])==>typeof(a[i][j])*==>int *
  • 第八个: typeof(&a) ---> int [3][4] *
                   &a+1:指向下一个数组a类型元素的首地址(加了一整个数组a的大小)

 指针变量作为函数的参数:

一定要记住:C语言中的函数参数传递永远是一个值传递;

把一个变量的地址传递给了函数,并且可以通过这个地址间接访问原来那个变量,不受作用于的限制;

数组做函数的参数

一维数组作为函数的参数:

int a[10];

       f(int p[],int n)
            {
                //p[i] ===> a[i]
            }           f(a,10)

也可以这样写:

 f_2(int *x,int n)
            {
                //x[i] ===> a[i]
            }

            f_2(a,10);

二维数组作为数组的参数: int a[3][4];

 typeof(a);//a是一个二维数组名,也是一个指针,是第一行的首地址 
        ===>typeof(&a[0]) ===> int [4] *
        ===> int (*x)[4]
            fun(int (*x)[4],int n)

字符串和指针

字符在计算机中是以ASCLL码值保存的,C语言中字符串是通过char*(字符型指针)来实现的
C语言的字符串,是用""(双引号)引出来的一串字符进行表示的,并且字符串后默认加了一个'\0'(终止符,ASCII码为0),这个就是字符串结束的标志 

 ""  字符串,字符串常量
        typeof("12345") ===> const char * 常量指针
        
        char *p = "abcde";
        *p = 'A';//ERROR,p指向的字符串是只读的,
        p[2] = 'A';//ERROR
        *(p+2) = 'A';//ERROR

    表示字符串的方法有两个:

  • char s[]="hello";  ==========>  表示字符数组
  • char *p="hello";  ==========>指针实现的字符串表达
指针常量和常量指针

常量指针:指针可以指向别的地方,但它指向的内容不允许被改变(字符串)

指针常量:指针的指向不允许被改变,但是可以改变上面的值(数组名)

用法和区别(待补充)

数组长度

字符串大小,数组元素的个数,一个字符数组,必须到它本身的\0才结束计算,而且,本身自带的\0也算数组长度的一个计算在内,数组内容里面出现‘\0’算一个字符;用sizeof去表示;

字符串长度

从传入的字符串首地址开始往下找,每有一个不是'\0'的字符的时候,长度+1,当碰到'\0'的时候,结束计算,并且'\0'不会计算在其中;用strlen去表示;


这是我在学C语言中,通过老师讲解和询问同学对自己的学习的一个总结,文中有不对或说法不准确的地方,恳请各位大佬指正!

本人的评论区欢迎大家讨论技术性的问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值