指针是个变量,它用来存放地址的变量(存放在指针的值都当作地址来处理)
指针和指针类型
<!--**指针类型**决定了指针进行解引用操作的时候能够访问空间的大小-->
int*p; *p能够访问4个字节
char*p; *p能够访问1个字节
double*p; *p能够访问8个字节
总结:指针的类型决定了指针向向或向后走一步有多大距离
-
无论指向什么类型,所有的指针的大小都是一样的,因为都是地址(4/8)
-
但是指向不同类型的指针是不能直接互相赋值的,这是为了避免用错指针
指针的类型转换
-
void* 表示不知道指向什么东西的指针,计算时与char*相同(但不相通)
-
指针也可以转换类型
-
int *p=&i; void * q =(void*)p;
-
这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量
-
我不再当你是int 我认为你是个void!
1+1=2?
-
给一个指针加1表示要让指针指向下一个变量
-
int a[10];
-
int *p=a;
-
*(p+1)--->a[1];
-
如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义
野指针
概念:是指针指向的位置是不可知的(随机的,不明确的,没有明确限制的)
成因:①指针为初始化
int* ptr
*ptr=20//非法访问
②指针越界访问
int arr[5]={0}
int i=0;
int* p=arr
for(i=0;i<10;i++)
{*p=1;
p++;
}
③指针指向的空间释放了
int* test()
{
int n=100;
return &n;
}
int main(){
int* p=test();
printf("%d",*p);
return 0;
}
2、assert断言
assert.h
头文件定义了宏assert()
用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行,这个宏常被定义为“断言”
assert(p!=NULL);
#define NDEBUG
#include<assert.h>
缺点:增加了运行时间
指针的使用和传址调用
strlen的模拟实现
size_t strlen(const char* str);
函数在调度的时候,传递的是地址
实参在传给形参的时候,形参会单独创建一份临时空间来接收实参,对形参的修改不影响实参
传址调用,可以让函数和主函数之间建立真正的联系,在函数内部可以修改主函数中的变量;所以未来函数中只是需要主函数中的变量值来实现计算,就可以采用传值调用。如果函数内部要修改主函数中的变量的值,就要用传址调用