指针是什么
指针是一个变量
带地址的传送门 (存放在指针中的值都被当成地址处理)存放在内存单元的地址(编号)
指针也是一个变量,只不过是指针类型的变量 指针的类型为所指向对象的类型
int main()
{
int i = 0;
int* j = &i;//j为指针变量,里面存的是指向对象的地址
printf("%d\n", *j);
return 0;
}
指针的类型
为什么存入的类型不同,打印的地址却一样
int main()
{
int i = 0;
int* pa = &i;
char* pc = &i;
printf("%p\n", pa);
printf("%p\n", pc);
return 0;
}
不同类型指针 在通过指针 改变 指向变量的区别!!
对指针进行解引用操作时 不同类型指针改变内存的大小不同
指针类型决定了指针进行解引用操作时,能够访问空间的大小(权重不同)
int main()
{
int i = 0x55667788;
int* pa = &i;
*pa = 1;
return 0;
}
int指针 类型改变了四个字节
&i
int main()
{
int i = 0x55667788;
char* pa = &i;
*pa = 1;
return 0;
}
char指针 类型改变了一个字节
那么double指针能够访问多少字节呐???
指针 + - 整数
对不同的 指针变量 加一 看地址位的变化
int main()
{
int i = 0x55667788;
int* pc = &i;
char* pa = &i;
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pa);
printf("%p\n", pa+1);
return 0;
}
指针类型决定了:指针走一步走多远(指针的步长)
int*p;p+1-->4bit
char*p;p+1-->1bit
double*p;p+1-->8bit
指针的使用
int main()
{
int arr[10] = { 0 };
int i = 0;
int* p = arr;//数组名为首元素地址 所以不需要 &
for (i = 0; i < 10; i++)
{
*(p + i) = 1;//每次地址走动4个字节正好对应数组的存放方式
printf("%d\n", arr[i]);
}
return 0;
}
指针申请的内存空间大小 8Byte 这是64位机器的结果 每次处理8个字节
解引用操作
可以直接对地址进行解引用操作,arr为首元素的地址所以可以对arr进行解引用操作
但是sizeof(arr) 和&arr都是对 数组 进行的操作
&arr[ i ] 是通过下标对数组某元素进行取地址操作
地址线
每一个地址都对应着唯一的选择(所有地址线通过与门的关系形成唯一一条路径)
8位机的内存 每次处理8bit
二级指针
二级指针的应用
在二级指针工作时一级的作用只有地址中转站的作用了,具体改变指向变量的空间大小由二级指针决定
二级指针为char类型 只能改变一个字节
此时一级指针为 int 类型
二级指针为int 类型 可以改变四个字节
此时一级指针为 char类型
野指针
指针指向的位置是不可知的(随机的,不准确的,没有明确限制的)
指针未初始化
int main()
{
int i;
int* p;//局部变量未初始化
*p = 10 ;//错误的 p 中的地址是非法的 随机的
return 0;
}
指针越界访问
int main()
{
int arr[10] = {0};
int* p=arr;
int i = 0;
for (i = 0; i < 12; i++)//超出数组元素的范围
{
*p++ = i; //指针越界就是野指针
}
return 0;
}
int main()
{
int arr[10] = {0};
int* p=arr;
int i = 0;
for (i = 0; i < 12; i++)
{
*p = i;
p = p + 1;//每一次加的是元素个数 是int 类型的4Byte
}
return 0;
}
指针指向的内存空间被释放
(封装函数里的变量内存)
int* test()
{
int i = 0;
return &i;//返回为地址 函数类型为指针
}
int main()
{
int* p = test();//接收为指针类型来接收
*p = 10;
return 0;
}
int* test()
{
int i = 0;
int* p = &i;
return p;//返回的类型为指针决定了函数的类型
}
int main()
{
int** pa = test();//是不是应该使用二级指针来接收??
**pa = 10;//pa指向的地址是临时的 此时已经被销毁
return 0;
}
static的使用
变量i出局部范围就注销了但是经过 static 的修饰变成静态局部变量,从外面可以使用指针进行访问,但是不可以直接引用变量i。i的地址和值被保存,但是范围还是局部范围。
int* test()
{
static int i = 0;
return &i;//返回为地址 函数类型为指针
}
int main()
{
int* p = test();//接收为指针类型来接收
*p = 10;
printf("%d\n", *p);
return 0;
}
NULL 空指针
NULL 为0,强制类型转换为空指针。
int main()
{
int a = 0;
int* p = &a;
int* pa = NULL;//空指针,不知道指向哪个地址,暂时赋值为0 但是类型为指针
p = NULL;//不使用这个地址了就把指针变量 p 赋值为空指针
return 0;
}
检查指针的有效性
int main()
{
int a = 10;
int* p = &a;
int* pa = NULL;
if (pa != NULL)
{
//指针为有效地址才使用这个指针
*pa = 10;//为空指针不能进入判断
}
return 0;
}
指针的运算
为什么最后打印的数不是数组的最后一个元素
#define N_values 5
int main()
{
float values[N_values]={1,2,3,4,5};
float* p=&values;
for (p = &values[0]; p < &values[N_values];)
{
*p++ = 0;//*p++ 先解引用 然后自增1 导致指针在最后变成野指针
printf("%f ", *p);//values[0]指向的变量没有打印
}
return 0;
}
稍微改一下就行 不要让指针越界变成野指针
指针减指针
指针减去指针得到是两指针中间的元素个数
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int ret = &arr[9] - &arr[0];
printf("%d\n", ret);
return 0;
}
不同类型的指针相减 得到的是随机数 没有意义
指针减指针必须满足 指针指向的是同一个数组的内存空间
指针求字符串的长度
计数的方式 函数递归的方式 指针的方式
int My_strlen(char* pa)//使用指针来接收首元素的地址{
{
char* star = pa;//star end是二级指针吗???
char* end = pa;//pa不需要进行解引用操作吗?? pa不是指针变量吗??
while (*end != '\0')
{
end++;
}
return end - star;
}
int main()
{
char arr[] = "ling song";
int ret = My_strlen(arr);//使用指针求字符串的长度
printf("arr[0]= %p\n", &arr[0]);
//printf("%d\n", ret);
return 0;
}
int My_strlen(char* pa)//使用指针来接收首元素的地址
{
int i = 0;
while (*pa != '\0')//字符串结束标志
{
pa++;//指针变量自增1 增加的 是元素的个数
i++;
}
return i;
}
int main()
{
char arr[] = "ling song";
int ret = My_strlen(arr);//使用指针求字符串的长度
printf("%d\n", ret);
return 0;
}
指针变量有没有自己的内存空间
star end是一级指针 ,里面存放的是地址,而不是指针。
指针变量是有自己的地址,只是变量里面存放是指向变量的地址
int main()
{
int i = 0;
int* p = &i;
printf("%p\n", &i);
printf("%p\n", p);
printf("%p\n", &p);
return 0;
}
指针数组
存放指针的数组