指针是什么
1.指针是内存中最小的单元编号,也就是地址(指针就是地址)
2.平时口语说的指针,通常指指针变量,是用来存放地址的变量
内存
指针变量
我们可以通过&取出变量的内存(地址),把地址放在变量中
#include <stdio.h>
int main()
{
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
中,p就是一个之指针变量。
return 0; }
取出变量的地址实际上是取出第一个字节的地址
总结
那么32根地址线 能产生2的32次方个地址
每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB ==
2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空闲进行编址。
同样的方法,那64位机器,如果给64根地址线,那能编址多大空间,自己计算。
2^32 * 2^ 32=4*4GB=16GB
到这里我们就能明白
总结
指针是用来存放地址的,地址是唯一表示一块地址空间的
地址的大小在32位平台是4个字节,64位平台是8个字节
指针和指针类型
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
指针不同的类型决定了指针解引用时 能访问地址的字节大小
指针加减整数
指针的类型决定了指针走一步能走几个字节
int main()
{
int a = 10;
int*pa = &a;
char* pc = &a;
printf("%p\n", pa);
printf("%p\n", pc);
printf("%p\n", pa+1);
printf("%p\n", pc+1);
return 0;
}
float values[5];
float *vp;
for (vp = &values[0]; vp < &values[5];)
{
*vp++ =0 ;
}
数组内存中的地址存放
讨论*和++的关系
可以理解为后置加加时先用指针p,前置加加时根据从右到左顺序
指针的解引用
指针的类型决定了,指针解引用时能有多大权限(操作几个字节)
char *访问一个字节,int *访问四个字节
int arr[10] = { 0 };
如果希望按照一个整型的形式访问
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*p = 0x11223344;
p++;
}
假设你希望,你访问这个40个字节的时候,是以字节为单位访问
char* p = (char*)arr;//int*
int i = 0;
for (i = 0; i < 40; i++)
{
*p = 'x';
p++;
}
int* test()
{
int a = 10;
printf("%d\n", a);
return &a;
}
int main()
{
int*p = test();
*p = 100;
}
将变量a销毁后将a的地址传给p,此时p就是&a,*p的地址是指针地址
野指针
野指针形成原因
1.未初始化
2.指针越界访问
3.指针指向的空间释放了
如何规避空指针
空指针不能解引用因此要写库函数assert 对应头文件为: assert.h
指针 减 指针
不使用变量的情况下构造my_strlen函数
int my_strlen(char* str)
{
char* start = str;
while (*str)
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
}
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[0] - &arr[9]);
return 0;
}
指针的关系运算
一般情况下不能用以下方法写
for(vp = &values[N_VALUES]; vp > &values[0];)
{
*--vp = 0;
}
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
*vp = 0;
}
标准规定
指针和数组
数组名字是首元素地址
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", arr+1);
printf("%p\n", &arr[0]);
printf("%p\n", &arr[0]+1);
printf("%p\n", &arr);
printf("%p\n", &arr+1);
二级指针
int a = 10;
int* pa = &a;//pa是指针变量(一级指针)
int** ppa = &pa;//ppa是一个二级指针
int*** pppa = &ppa;//pppa就是三级指针
二级指针的运算
已知int *pa=&b; int* *pa=&pa;
*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa ,*ppa 其实访问的就是 pa .
int b = 20; *ppa = &b; //等价于 pa = &b;
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;
指针数组
就是一个数组存放了多个指针
一维数组
//int arr[5];//指针数组 - 存放整型的数组
//char ch[6];//字符数组 -存放字符的数组
int a = 10;
int b = 11;
int c = 12;
int d = 13;
int e = 14;
int* arr2[5] = {&a, &b, &c, &d, &e};//指针数组
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", *(arr2[i]));
}
二维数组
int data1[] = { 1,2,3,4,5 };
int data2[] = { 2,3,4,5,6 };
int data3[] = { 3,4,5,6,7 };
//arr就是一个指针数组
int* arr[3] = { data1 ,data2, data3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");