一、指针
1、什么是指针?
①在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量。指针一般用来存储变量的地址。
如图:0x0018上存储的是一个int类型的变量,值为10,指针就是0x0001,int型指针存放的是int变量的地址。
②指针的一般形式:
<存储类型><数据类型> *<指针变量名>
#include<stdio.h>
#include<string.h>
int main()
{
int a=10;
int *p=&a;
printf("P指针的地址是:%d,int变量的地址是:%d\n",&p,&a);
printf("P指针的值:%d,int变量的值%d\n",p,a);
printf("P指针解引用后的值%d\n",*p);
return 0;
}
可以通过上述例子对指针有更深刻的认识
②解析&p、*p、p
p——指针变量,它的内容是指向变量的地址量
&p——指针变量占用的存储区域的地址 ,是个常量
*p——指针所指向的对象,它的内容是数据
③指针所占字节长度
无论什么类型的指针,所占字节长度都是固定的,32位的占4个字节,64位的占8个字节
#include<stdio.h>
#include<string.h>
int main()
{
char c='a';
char *pc=&c;
int a=10;
int *p=&a;
double b=10;
double *pb=&b;
printf("char型指针pc的字节长度:%d,char型变量的字节长度:%d\n",sizeof(pc),sizeof(c));
printf("int型指针p的字节长度:%d,int型变量的字节长度:%d\n",sizeof(p),sizeof(a));
printf("double型指针pb的字节长度:%d,double型变量的字节长度:%d\n",sizeof(pb),sizeof(b));
return 0;
}
2、指针的运算
①直接使用指针运算:本质上是指向地址的移动
比如:指针p做++操作:p++,根据指针变量类型向后跳其类型所占字节数的长度
简单来说就是,char类型指针就是地址往后跳1个字节,int类型指针就是地址往后跳四个字节,double类型指针就是地址往后跳8个字节,以此类推。
综上:p+n表示的实际的地址量为:p+sizeof(p的类型)*n
#include<stdio.h>
#include<string.h>
int main()
{
char c='a';
char *pc=&c;
int a=10;
int *p=&a;
double b=10;
double *pb=&b;
printf("char类型指针地址:%d,",pc);
++pc;
printf("自增后地址:%d\n",pc);
printf("int类型指针地址:%d,",p);
++p;
printf("自增后地址:%d\n",p);
printf("double类型指针地址:%d,",pb);
++pb;
printf("自增后地址:%d\n",pb);
return 0;
}
②使用指针操作所指向的字符串:
比如:想要使用指向int变量的int型指针操作int型变量,使变量自增操作
使用的语句是:(*p)++;
这里的小括号是因为++运算符的优先级高于解引用*运算符
在不确定优先级的情况下,可以根据运算先后顺序加括号
#include<stdio.h>
#include<string.h>
int main()
{
int a=10;
int *p=&a;
printf("使用指针使变量自增操作前:指针解引用为%d,int变量的值为%d\n",*p,a);
(*p)++;
printf("使用指针使变量自增操作后:指针解引用为%d,int变量的值为%d\n",*p,a);
return 0;
}
二、指针与数组
1、数组的指针
是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址
使用指针指向数组,指向数组首地址
int a[10];
int *p=a; //指针变量指向数组首地址
当需要访问数组第i+1个数组元素时,以下四种方法具有相同的功能
/*
1、a[i] //使用数组下标的方法
2、*(p+i) //使用指针的地址移动再解引用的方法
3、*(a+i) //使用地址直接+i ,a相当于地址
4、p[i] //指针与下标的方法
注意:不能使用数组名进行运算操作,例如:a++,a+i
*/
2、小练习:将整形数组中n个数按反序存放
#include<stdio.h>
#include<string.h>
int main()
{
int a[]={20,12,6,59,3,26};
int n=sizeof(a)/sizeof(int); //数组长度
int *p,*q,i; //左指针、右指针
p=a; //左指针指向数组头
q=&a[n-1]; //右指针指向数组末尾
while(p<q)
{
int temp=*p;
*p=*q;
*q=temp; //一前一后两两交换
p++;q--;
}
for(i=0;i<n;i++)
printf("%d ",a[i]); //打印输出
return 0;
}
3、指针与二维数组
1、多维数组就是具有两个或两个以上下标的数组
(C语言中,二维数组的元素连续存储,按行优先)
例如:一个a[3][3]的二维矩阵,空间上是连续存储的
小tips:由于二维数组空间是连续存储的,那怎样编写程序更高效呢?比如有一个n行m列的二维数组,下面哪种编程方法更高效?
第一种:
for(i=0;i<n;i++)
for(j=0;j<m;j++)
printf("%d,",a[i][j]);
第二种:
for(j=0;j<m;j++)
for(i=0;i<n;i++)
printf("%d,",a[i][j]);
2、二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址。
二维数组定义指针:<存储类型> <数据类型> (*<指针变量名>)[表达式] ;
#include<stdio.h>
#include<string.h>
int main()
{
int a[2][3]={20,12,6,59,3,26};
int (*p)[3],i,j;//定义列指针
p=a;//将指针指向二维数组
for(i=0;i<2;i++)
for(j=0;j<3;j++)
printf("%d,%d,%d,%d\n",a[i][j],p[i][j],*(*(a+i)+j),*(*(p+i)+j));
//二维数组的四种访问形式
return 0;
}