指针
指针常量:和地址常量相同 指针变量:用来存储指针常量
指针:通常将指针常量和指针变量统称为指针
以字节为单位将内存进行划分,没一个字节的空间都有一个地址编号首地址:某一段空间的 第一个地址编号
指针永远为4个字节指针的一般形式:
数据类型 *指针变量名例如:int a = 10;
int *p =&a;
p:存储a这段空间首地址的变量 &a:a这段空间的首地址取地址符:&
取值符号:*
取值符号和取地址符互为逆运算初始化: int *p;
野指针:指针随机指向某一段空间; 操作野指针可能会出现段错误int *p=NULL;
空指针:指针指向地址编号为0的那一段空间。 操作空指针一定会出现段错误如何调试段错误
gdb调试工具
gcc -g 文件名.c gdb ./a.out
r(run)执行文件
q退出指针运算
p+1:会发生指针偏移,偏移的是所指向数据的数据类型p++ ++p p p
p>q:一般情况下运用在某一段连续的空间
p-q:一般情况下也是运用在某一段连续的空间才有意义
查询内存的保存形式(大端存储或小端存储) #include
int main(int argc ,congst char *argv[] )
{
int a = 0x12345678; int *p = &a;
printf("%#d\n",(char)*p); return 0;
}
输出:0x78 说明计算机内存是小端存储。
指针和数组的关系
int a[3] ={1,2,3}; 数组名:
a: 1、代表整个数组
2、数组名是一个地址常量,是数组所在内存空间的首地址
一级数组内部关系:
int a[3]={1,2,3};
a = &a[0]; a+1=&a[0]+1=&a[1];
*(a+1)=*(&a[1])=a[1];
结论: *(a+n)= a[n];
一维数组和一级指针的关系int *p=a; p+1=a+1=&a[0]+1=&a[1];
*(p+1)=*(a+1)=*(&a[0]+1)=*(&a[1])=a[1];
*(p+1)=p[1];
结论:*(p+n)=*(a+n)=a[n]=p[n];
二维数组内部关系
int a[2][3]={{1,2,3},{4,5,6}};
a=&a[0]; a+1=&a[0]+1=&a[1];
*(a+1)=*(&a[0]+1)=*(&a[1])=a[1]
将a[1]看做一个一维数组的数组名a[1] = &a[1][0]
a[1] + 1 = &a[1][0] + 1 = &a[1][1]
*(a[1] + 1) = *(&a[1][0] + 1) = *(&a[1][1])
*(a[1] + 1) = a[1][1]
*(*(a + 1) + 1) = a[1][1]
结论: *(*(a + i) + j) = a[i][j]
二维数组和数组指针的关系
int a[2][3];
int (*p)[3]=a;
p + 1 = a + 1 = (&a[0] + 1) = &a[1]
*(p + 1) = *(a + 1) = *(&a[0] + 1) = *(&a[1]) = a[1] = p[1] p[1] + 1= a[1] + 1 = &a[1][0] + 1 = &a[1][1]
*(p[1] + 1) = *(a[1] + 1) = *(&a[1][0] + 1) = *(&a[1][1])
*(p[1] +1) = *(a[1] + 1) = a[1][1]
结论:*(*(p+i)+j)=*(*(a+i)+j)=a[i][j]=p[i][j]
#include
{
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1); int *ptr2=(int *)((int)a+1);
printf("%x,%x",ptr1[-1],*ptr2); return 0;
}
输出结果:5,2000000
字符指针
字符指针可以用来接受字符串,其实是接收字符串的首地址,但是不可以通过*的方式去修改,否则会发生段错误。
指针习题
程序:
输出: