在计算机科学中,指针( Pointer )是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
指针是个变量,存放内存单元的地址(编号)。
#include
int main()
{
int a = 10;//在内存中开辟 一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//将a的地址存放在p变量中,p就是一一 个之指针变量。
return 0;
}
总结:指针就是变量,用来存放地址的变量。( 存放在指针中的值都被当成地址处理)。
问
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,假设有32根地址线,那么假设每根地址线是产生一个电信号正电/负电 ( 1或者0 )
那么32根地址线产生的地址就会是:
这里就有2的32次方个地址。
每个地址标识一个字节,那我们就可以给 (232Byte ==232/1024KB==232 /1024/1024MB==232/1024/1024/1024GB == 4GB) 4G的空闲进行编址。
这里我们就明白:
总结:
指针类型决定了指针进行解引用操作时,能访问的空间大小
int* p:p可访问4个字节
char p:p可访问1个字节
float p:p可访问4个字节
double p:*p可访问8个字节
参考如下代码
int main()
{
int arr[10] = { 0 };
int *p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
return 0;
}
int main()
{
int arr[10] = { 0 };
char* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
return 0;
}
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1.指针未初始化
int main()
{
int *p;
*p = 20;
return 0;
}
这里的p就是一个野指针
p是一个局部的指针变量,局部变量不初始化的话,默认是随机值。*p = 20非法访问内存了。
2.指针越界访问
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 11; i++)
{
*p = i;
p++;
}
return 0;
}
当指针指向的范围超出数组arr的范围时,p就是野指针
3.指针指向的空间释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int*p = test();
*p = 20;
return 0;
}
test是创建的临时函数,使用过后就被销毁了,这时指针访问的就是一个已被销毁的变量,此时的指针就变为了野指针
1.指针初始化
int main()
{
int *p = NULL;
return 0;
}
int main()
{
int a = 10;
int* ptr = &a;
return 0;
}
2.小心指针越界
3.指针指向空间释放即使置NULL
4.指针使用之前检查有效性
1.指针 + - 整数
指针前后移动
2.指针 - 指针
指针间的距离
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", &arr[9] - &arr[0]);
return 0;
}
指针和指针相减是有前提的: 两个指针指向同一块空间
需避免如下代码
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char c[5];
printf("%d\n", &arr[9] - &c[0]);
return 0;
}
练习:用指针模拟实现strlen函数
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
int n = my_strlen("abc");
printf("%d\n", n);
return 0;
}
数组名表示的是数组首元素地址
看下面代码
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d]=%p<==>p+%d=%p\n", i, &arr[i], i, p + i);
}
return 0;
}
小知识
arr[i]不但可以写为p+i还可以写为i[arr],p[i],i[p]
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d[arr]=%d ", i, i[arr]);
printf("p[%d]=%d ", i, p[i]);
printf("%d[p]=%d ", i, i[p]);
printf("\n");
}
return 0;
}
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就引出了二级指针。
对于二级指针的运算
int b = 20;
*ppa = &b;//等价于pa = &b;
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;