- 定义指针
#include <stdio.h>
int main()
{
//1.指针也是一种数据类型
int * p;
p = (int *)123;
printf("%d\n",(int *)p);
//2.指针指向谁,就是把谁的地址赋值给指针
int a = 10;
p = &a;//P保存了a地址
//%p打印地址,是以16进制方式打印
printf("%p, %p\n",p, &a);
//3.如果直接操作指针变量本身没有意义
//4.需要操作*p,操作指针所指向的内存
*p = 100;//*p相当于a 把100给p指向的地址
printf("%d ,%d \n",*p,a);
return 0;
}
- 指针变量和指针所指向的内存的区别
#include <stdio.h>
int main()
{
int a = 10;
//*有两层含义
//1.定义变量时,*代表是类型,他不是指针类型int *
int *p;//定义指针类型变量p
p = &a;//取a的地址
//2.在使用变量时,*代表操作指针所指向的内存
*p = 100;//给地址*p指向的地址赋值
printf("a = %d\n",a);
int b =11;
p = &b;//取b地址
*p = 200;//给地址*p指向的地址赋值
printf("a = %d, b = %d\n",a,b);
return 0;
}
- 同类型变量赋值
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;//取a地址
*p = 111;//给p指向的地址 a赋值111
int *q;
q = p;//把p的内容给q(把a的地址给q)
*q = 222;//给q指向的地址 a赋值222
//打印 a的地址,p q 的值(q p指向的地址)
printf("&a = %p , p = %p , q = %p \n",&a,p,q);
//打印 a的值,q p指向的地址内的值
printf("a = %d , *p = %d , *q = %d \n",a,*p,*q);
return 0;
}
- 野指针:这个指针变量保存了一个没有意义(非法)的地址。
a.只有定义后的变量, 此变量的地址才是合法的地址。
b.野指针就是保存没有意义地址的指针变量。
c.操作野指计变量本身不会有任何问题。
d.操作野指针所指向的内存,才导致段错误。
#include <stdio.h>
int main()
{
int *p;
p =(int *) 0x1234;
printf("p = %d \n",p);
*p = 100;//会出问题,0x1234地址未被定义
return 0;
}
- 空指针(不会出现野指针情况)
#include <stdio.h>
int main()
{
//1.空指针,给指针变量赋值为NULL
//2.NUL就是数字0
int *p = NULL;
if( p != NULL)
{
*p = 100;
}else{
printf("空指针\n");
}
int a = 11;
p = &a;
if( p != NULL)
{
*p = 100;
printf("a = %d\n",a);
}else{
printf("空指针");
}
return 0;
}
- 指针大小
#include <stdio.h>
int main()
{
//1、32位编译器用32位大小(4字节)保存地址
//2、64位编译器用64位大小(8字节)保存地址
int a = sizeof(int *);
int b = sizeof(char *);
double *p;
int c = sizeof(p);
printf("a = %d, b = %d, c = %d \n",a,b,c);
return 0;
}
7. 多级指针
#include <stdio.h>
int main()
{
//如果定义一个合适类型的变量保存另一个变量的地址
//在需要保存变量地址的类型基础上加一个*
int a = 10;
int *p = &a;//保存a的地址
int **q = &p;//保存p的地址
int ***t = &q;//保存q的地址
//操作时
*t;//表示->q
**t;//表示->p
***t;//表示->a
return 0;
}
- 指针步长
#include <stdio.h>
int main()
{
//1.指针的加法不是传统的加法;
//2.步长由指针指向的数据类型决定
int a;
int *p = &a;
printf("p = %d,p+1 = %d \n",p,p+1);//步长地址+4
char b;
char *q = &b;
printf("q = %d,q+1 = %d \n",q,q+1);//步长地址+1
return 0;
}
- 万能指针
#include <stdio.h>
int main()
{
//1.我们不可以定义void(无)普通变量,不能确定类型,编译器即不知道分配空间。
//void a;错误
//2.可以定义void *变量,void *指针叫做万能指针。
//3.void *可以指向任何类型的变量,使用指针所指向的内存时,最好装换为它本身的指针类型。
void *p = NULL;
int a = 10;
p = &a;
//void指针没有类型,p =222;就会出错,编译器不知道指针指向的类型空间大小;所以需要强制转换。(不做类型转换,无法确定步长)
*((int *)p) = 222;//转换为被操作的类型指针的指针
printf("*p = %d\n",*((int *)p));
}
- conct修饰的指针变量
#include <stdio.h>
int main()
{
//1.指针变量
//2.指针所指向的空间
//3.const 修饰经跟它其后的类型,同时该类型就为只读模式
int a = 10;
int *p = &a;
*p = 100;//等价于操作a,*p操作指针指向的空间
p = NULL;//操作指针变量,把指针p赋值为空
//const 修饰 *,代表指针指向的内存是只读的
const int *p2 = &a;
//*p2 = 100;//就会错
p2 = NULL;//没错
int const *p3 = &a;//等价于 const int *p2 = &a;
//*p3 = 100;//错
p3 = NULL;//OK
//修饰指针变量值,代表指针变量p4的值只能是可读
int * const p4 = &a;
*p4 = 100;//OK
//p4 = NULL;//error
//修饰指针变量值、*,代表指针变量p4的值和指针指向的地址都只能是可读
const int * const p5 = &a;
//*p5 = 100;//error
//p5 = NULL;//error
return 0;
}
总结:
a.指针变量也是一个变量,是变量就可以赋值。
b.指针指向谁,就是把谁的地址给指针。
c.*p操作的是指针所指向的内存地址。
d.p等价于(p+0),同时等价于p[0],都是操作指针所指向的内存地址。
e.&q是去q在内存的地址,不是获得q内存的值。