C语言指针1
一:1、地址:内存单元的编号
内存单元的值:内存单元中存放的内容
通过地址可以找到内存单元格,然后再取出内容
2、指针:就是地址
3、对变量进行数据存取有几种方式
两种:直接存取 int a=10; a=a+10;
间接存取 通过指针
二: 1、指针变量
就是用来存放(指针)地址的变量
注意:指针(地址)和指针变量是两码事
指针变量使用流程:先定义 ---> 初始化 -->使用
2、指针变量定义
格式:数据类型 *指针变量名;
指针变量名 严格遵守标识符命名规范
int a;
char c;
double d1;
int *p; //描述:定义了一个指针变量,变量名是p ,它可以存放一个整型(int)数据的地址
注意:
1)指针变量只能存放地址
2)int *p中,"*"表示定义一个指针变量
3)指针变量也有作用域(全局的、静态、局部)static修饰局部变量局部变量的生命周期延长
4)定义指针变量指向的话,要注意指针的类型,因为当使用指针操作指针指向内存单元内容时,会按照指针的类型到内存中寻址,因此可能会出现问题。
3、指针变量的初始化
把谁的地址给指针变量,就可以理解为,这个指针变量指向这个变量
1)定义的同时初始化
“&” 用此符号可以取得一个变量的地址
int a;
char c;
double d1;
int *p1=&a; //&a 获取的变量a的地址 scanf("%d",&a);
char *c1=&c;
double *dp=&d1;
int *p2 = &c;(错误的,p2只能存放一个int型数据的地址)
int *p3 = 100;(错误的,p3用来存放地址的,不能存放整型的数
2)先定义,后初始化
1)变变量的地址进行初始化
int *p3;
p3 = &a; //给p3指针进行初始化
2)用指针变量,初始化另外一个指针
int *p4=&a;
int *p5;
p5 = p4; //p4存放的时一个地址,可以直接赋值给p5
3)指针变量可以初始化为NULL
NULL 空 (不是0 “ ” ‘ ’)
int *p2 = NULL
用0赋值为空
int *p3=0;
错误:
int *p6=&a;
char *c2=&c;
int *p7 = c2; 错误的,因为p7只能存放int型数据的地址 c2是一个char型变量的地址
三:指针变量的引用:
& 获得一个变量的地址
* 两种用法
1)在定义指针变量的时候,表示定义的时一个指针变量
2)*指针变量名 表示取得指针变量中存放的那个地址对应的存储单元的值
int a = 9; int *p1 = &a;
*p1 9, //获取a的地址,对应的值
四:指针使用场景:
指针的使用场景1:
在被调函数中,访问主调函数中的变量
例如:void change(int *p){
*p = 100;
}
指针的应用场景2:
一个函数可以有多个返回值(原理上同指针使用场景1)
例如:void yunsuan(int a,int b,int *add,int *jian,int *cheng,int *chu){
*add = a+b; // *add 访问add指针变量存放的地址的对应存储单元的内容
// add = 0x01 *0x01 取得地址对应的值
*jian = a-b;
*cheng = a*b;
*chu = a/b;
}
五:多级指针:
int a = 10; int p = &a; int **p2 = &p; int ***p3 =&p2;
printf("a = %d\n",a); //10
printf("a addr = %p\n",&a); //a的地址
printf("*p = %d\n",*p); //10
printf("p addr = %p\n",&p); //指针变量p的地址
printf("*p2 = %p\n",*p2); //p的内容,a的地址
printf("**p2 = %d\n",**p2); //10 *(*p2) = *(a的地址) = 10
printf("***p3 = %d\n",***p3); // 10 **(*p3) = *(*p2) = *p = 10
六:指针为什那么要区分类型:
疑惑点:
1)数据占用的字节数是不一样的,但是为什么指针用都8个字节
指针变量用来存放地址,地址的占用的字节数是一样的,
2)既然指针变量都是占用8个字节,为什么要还有区分指针类型呢
int a = 266;
char *pc = &a;
printf("*pc = %d\n",*pc);// 打印结果有问题?因为char类型的指针会在内存中寻址,寻址一个字节的内存,而int类型的变量占四个字节;
七:1、数组的指针的概念:
数组元素的指针
定义一个指针变量,指向数组的某一个元素
注意:
int a[5];
int *p = &a[1];
int *p1 = &a[0]; //&a[0] == 数组的首地址 == 数组名
//p1指向数组了
2、用数组指针引用(访问)数组元素
引入数组指针的概念主要是为了
,用指针引用数组的每个元素(其实就是用指针间接访问a[0] a[1]。。。。。)
1)用数组名引用数组的元素
a[0] a[1] ....... (用数组名直接访问)
用数组的首地址(数组名)进行访问
a+0 --> a[0] a+1 --> a[1] a+2 --->a[2]
2)用指针引用数组的元素
用数组指针访问数组元素
int *p=a;
int *p1=&a[0];
p+1 a[1] //a+1
p+2 a[2]
3)疑惑:既然用数组名和数组指针都可以访问数组,为什么还要使用指针?
使用指针比较灵活
体现在:
for (int i=0; i<3; i++) {
printf("p+%d = %d\n",i,*(p++)); //*p p = p+1 *p-->a[1]
}
4)数组名和指针变量的区别
int a[10]; //a数组名 是一个常量 a+1 a+2 ;
int *p = a; //p是一个指针变量,p = p+1 可以,p++
注意:1>p+1指指针变量所指向地址的偏移量,如果int行指针变量偏移4个字节
2>数组a++不正确,因为数组名a为常量,不能a=a+1,
八: 指针数组:
数组中的每一个元素都是地址(指针)
int a[3][3]={1,2,3,4,56,7,8,120,11};
//定义一个指针数组名为pa 有三个元素,a[0],a[1],a[2]三个地址
int *pa[3]={a[0],a[1],a[2]};
*(pa+1)
注意:数组指针是指向数组的指针,指针数组是存放指针(地址)的数组