目录
指针分类
1.基本类型指针(重要)
2.指针和数组
3.指针和函数
4.指针和结构体(重要)
5.多级指针
#include<stdio.h>
int main(void)
{
int * p;//p是变量的名称,p变量的数据类型是int *类型,int *表示p变量存放的是int变量的地址
int i=3;
int j;
p=&i;//int * p,p=&i可以写成int * p=&i
/*1.p保存了i的地址,所以p指向i
2.p不是i,i也不是p,修改p的值不影响i的值,修改i的值不影响p的值
3.如果一个指针变量指向了某个普通变量,则*指针变量就完全等同于普通变量,
所有出现*p的地方都可以替换成i,所有出现i的地方都可以替换成*p
*p是以p的内容为地址的变量,即以i的地址为地址的变量,即变量i
*/
//p=i;//error,因为类型不一致,p只能存放int变量的地址
j=*p;//*p=i,j=i;
printf("i=%d,j=%d\n",i,j);//i=3,j=3
return 0;
}
地址:内存单元的编号
从0开始的非负整数
范围:4G(0---4G-1)(8B=4GB)
&,*(指针)与++,--运算符同级(2级),具有右结合性(自右向左)
指针加减1,变换的是数据单元的字节数,加减1实际为跳过一个数据单元(int为4字节,float为8字节)
指针和指针变量
指针就是地址,地址就是指针,地址就是内存单元的编号
指针的本质就是一个操作受限的非负整数(只能减法,不能加乘除)
指针变量是存放地址的变量
指针和指针变量是两个不同的概念,但是我们叙述时会把指针变量简称指针
指针常见错误
#include<stdio.h>
void main()
{
int a;
int * p;
p=&a;
printf("%d\n",p);//没有对a初始化,p里面是垃圾值
}
#include<stdio.h>
void main()
{
int a=10,b=20;
int * p;
p=&a;
*p=b;//p中储存的地址不会变成b,只是将b的值赋给a
}
#include<stdio.h>
int main(void)
{
int * p;
int i=5;
*p=i;//p有指向,*p没有初始化,内容为垃圾值,用i=5修改了不属于这个系统的单元
printf("%d\n",*p)
return 0;
}
#include<stdio.h>
int main(void)
{
int * p;
int * q;
p=&i;
//*q=p;//有语法错误,*q是int型,p是int *型
//*q=*p;//error
p=q;//q是垃圾值,q赋给p,p也是垃圾值
printf("%d\n",*q)//13行
/*
q的空间是属于本程序的,所以本程序可以读写q的内容,
但如果q的内部是垃圾值,本程序就不能读写*q的内容,
因为此时*q所代表的内存单元的控制权限没有分配给本程序,所以到13行会报错
*/
return 0;
}
经典指针程序——互换两个数字
include<stdio.h>
void main()
{
int a=3;
int b=5;
int t;
t=a;
a=b;
b=t;
printf("a=%d,b=%d",a,b)
}
#include<stdio.h>
void huhuan_1(int * p,int * q)
{
int * t;//要互换p,q的值,p,q均为int *,所以t也应该是int *,不能是int
t=p;
p=q;
q=t;
}
void main()
{
int a=3;
int b=5;
huhuan_1(&a,&b);//(*p,*q)是错误的,未定义;(a,b)是错误的,变量是p,应该把a发送给p
printf("a=%d,b=%d",a,b);//不能成功互换
/*a,b的地址是死的,只能互换p,q的值,
p,q内存储的地址变化,但是a,b的值没变
*/
}
#include<stdio.h>
void huhuan_2(int * p,int * q)
{
int t;
t=*p;
*p=*q;
*q=t;
}
void main()
{
int a=3;
int b=5;
huhuan_2(&a,&b);
printf("a=%d,b=%d",a,b);//要改变a,b的值,就要互换*p,*q
}
#include<stdio.h>
void main()
{
int * p1,* p2,* p,a,b;
scanf("%d,%d",&a,&b);
p1=&a,p2=&b;
if(a<b)
{p=p1;
p1=p2;//数据交换的是指针,改变指向
p2=p;
}
printf("a=%d,b=%d",a,b);
printf("max=%d,max=%d",*p1,*p2);
}
#include<stdio.h>
void main()
{
int * p1,* p2,* p,a,b;
scanf("%d,%d",&a,&b);
p1=&a,p2=&b;
if(a<b)
{p=*p1;
*p1=*p2;//指向关系没有变,交换的是a,b的值
*p2=p;
}
printf("a=%d,b=%d",a,b);
printf("max=%d,max=%d",*p1,*p2);
}
指针和数组
1.指针和一维数组
(1)一维数组名:一维数组名是个指针常量//int a[5],b[5];a=b//error,a(一维数组名)是常量
它存放的是一维数组第一个元素的地址
(2)访问一维数组:下标法:a[3]或者p[3]
指针法 :*(a+i)或者*(p+i), p[i]等价于*(p+i)
可以 ++p 指向下一个数组元素,然后用*p取得元素的值。
不能用a++或者++a把指针指向下一个数组元素,数组名指针常量。
(3)确定一个一维数组需要几个参数(如果一个函数要处理一个一维数组,则应该接收该数组的那些信息)
两个参数:数组第一个元素的地址,数组的长度
(4)指针变量的运算
指针变量不能加乘除,只能相减
如果两个指针变量指向的是同一块连续空间中的不同存储单元,这两个指针变量才能相减
//p=&i,q=&j,p-q没有意义;p=&a[1],q=&a[4],q-p表示q和p所指向单元相隔的单元个数
#include<stdio.h>
void main()
{
int a=10;
int * p;
p=&a;
printf("%d\n",p);//if p=200
printf("%d\n",p+1);//p+1=204(一个整型变量是4个字节)
printf("%d\n",*p);//10
printf("%d\n",*(p+1));//垃圾值,因为没有为这个特定的内存地址分配一个整形变量
}
(5)一个指针变量占几个字节
sizeof(数据类型)返回值就是该数据类型所占的字节数
sizeof(变量名)返回值是该变量所占的字节数
p指向char类型变量(1个),q指向int(4个),r指向double(8个)
但p,q,r本身只占4个字节
2.指针和二维数组