在了解指针前需要了解一下内存的存储区域区别
常量区
存放一些常量字符串,常量区里面的内容是不可以更改的。
堆
存放对象
栈
存放局部变量,栈里面的内容可以随便更改
指针(指针变量的作用只用来存储地址)
指针的定义:变量类型 *变量名
例如:
int a=90; #这里定义了一个整型变量
int *p #这里的指针变量名是 p *号只是指针变量的标识。
p=&a; #这里就是指针变量p指向了a变量,因为指针变量
只能用来存储地址所以前面加&符号,表示把a变量的地址给指针变量p
注意:指针只能指向相同类型的变量,如果指向了不同类型的变量取值会出现错误
指针变量未经过初始化,不要拿来间接访问其他存储空间
例:
int *p=&a; #这是正确的写法,可以把int *看做成一个整体
*p=&a; #这是错误的写法,*p代表访问指针变量p指向的存储空间
p=&a; #这是正确的写法,是把变量a的地址给了指针变量p的存储空间
在定义指针变量时“*”号仅仅是一个象征,没有其它特殊含义(告诉你这是一个指针变量,
没有取值这一说)
指向指针的指针
把需要指向的指针类型拷贝过来加一个*
例:
int a=10;
int *p=&a;
int **p1=&p;
int ***p2=&p2;
指向数组的指针(指针与数组可以说他们两没有什么区别,可以相互访问)
数组名就是数组的地址,也是数组首元素的地址(并不是整个数组)
例:
int ages[3] ={1,2,3};
int *p;
p=&ages[0]; #指针变量p指向了数组的元素。
//p=ages; #这样指也是对的,因为数组名就是数组的地址
数组元素的访问方式
1.数组名[下标] ages[0]
2.指针变量名[下标] p[1]
3.指针标识符 (指针变量名 +n) *(p+n)
指针变量的+1 并不是加1 而是取决于指针的类型(如:int +4)
指针与字符串
字符串在C语言中是用字符数组来存储的。当用指针指向字符串,指向的是首字符,也就相当于指向了
整个字符串,从第一个开始读取一直到遇到“\0"为止
定义字符串的2种方式
1.利用数组
char name[]="jock";
特点:字符串里面的字符是可以修改的
2.利用指针
char *name="jock";
特点:字符串其实是一个常量字符串,里面的字符是不能修改的
返回函数的指针
定义格式:
返回值类型 *函数名(){
返回值
}
指向函数的指针
格式:返回值 (*变量名)(形参);
如:void (*p)(); #(*p)是固定写法,代表指针变量p将来肯定指向的是函数
#左边的 void:指针变量p指向的函数没有返回值
#右边的():指针变量p指向的是函数没有形参
定义指向函数的指针例如:
方法:
double funn(double a,char *b,int c){}
指向函数的指针
double (*p)(double ,char *, int)=funn;
调用函数
(*p)(5.3,"jak",10); #推荐这种调用方法
p();
指向结构体的指针
定义结构体:
struct student
{
int age;
char *name;
};
定义结构体变量并赋值
struct student stu={18,"jack"};
定义结构体指针并指向结构体变量
struct student *p=&stu;
访问指向结构体的三种方式:
printf("姓名:%s,年龄:%d\n",stu.name,stu.age);
printf("姓名:%s,年龄:%d\n",(*p).name,(*p).age);
printf("姓名:%s,年龄:%d\n",p->name,p->age); #常用访问方式