首先内存的细分:是由一个个字节的内存单元,每一个内存单元都有自己的地址。
指针是什么?
指针是变量,用来存放内存单元的地址。
#include
int main()
{
int a=10;//在内存中开辟一块空间
//这里我们对变量a,取出它的地址,可以使用&操作符.
//将a的地址放在p变量中,p就是一个指针变量.
int* p=&a;
return 0;
}
指针能表示的大小其实是地址线的位数决定的。
32位的平台下,指针表示的大小就是4个字节。64就是8个字节。
可以分为整形指针,字符指针,数组指针,函数指针等。
这两个是比较常见和容易理解的指针,依次用int和char表示,他们的区别在于指向变量类型不同,内存也不一样,在进行解引用操作时访问的字节大小也因为变量类型的区别会有所差异。整型指针可以访问4个字节,而字符指针只能访问1个字节。也就是说对整型指针变量解引用,一次可以操作一个整型,而对字符变量解引用一次只能操作一个字符。
较为特殊的charp="hello"这并不是将整个字符串的地址传个了p,而是传了字符串首元素‘h’的地址,可以通过’h‘的地址来找到整个字符串。此时出现charp2=“hello”,p2和p代表的是同一处地址,因为hello是常量字符串,没有必要开辟两块不同的空间的来存储它。这是字符指针的一个特性。
void型的指针可以接受任何类型的地址,但是不能对void型指针进行解引用操作。解引用操作要有特定的访问字节的数量,比如对整型指针解引用就是访问4个字节,字符型指针解引用就是访问1个字节,而void型指针无法确定访问字节个数,所以不能进行解引用操作。同时void*这种类型的指针也不能进行加减整数的操作,因为无法确定跳过的字节个数。
数组指针本质是指针,用法: int (*p) [10] 。表示它指向数组的指针。这个数组中含有10个元素,每个元素都是整形。
区别于指针数组:
int * p[10]。表示的是指针数组,这个数组有10个元素,每一个元素都是整形的指针。
无关。
32的编译器:指针只能是32位的四个字节大小。
若指针类型为int * 的指针+1,那么它将跳过4个字节的大小指向4个字节以后的内容:
若指针类型为char*的指针+1,那么它只会跳过1个字节的大小指向下一个字节的内容。
解引用
指针的类型决定了指针向前或向后走一步有多大距离。
指针的类型决定了指针在进行解引用操作时,能向后访问的空间大小.
成因:
#include
int main()
{
int* p;
*p=10;
return 0;
}
#include
int main()
{
int arr[10] = { 0 };
int* p = &arr[0];
int i = 0;
for (i = 0; i < 11; i++)
{
*p++ = i;
}
return 0;
}
#include
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
return 0;
}
指针变量p得到地址后,地址指向的空间已经释放了,所以这个时候的p就是野指针。(局部变量出了自己的作用域就被释放了)
当不知道指针将要用于存放哪一变量地址时,在创建指针变量时应置为空指针(NULL)
#include
int main()
{
int a = 10;
int* p1 = &a;//明确知道存放某一地址
int* p2 = NULL;//不知道存放哪一地址时置为空指针
return 0;
}
#include
int main()
{
int arr[5] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 5; i++)
{
*(p + i) = arr[i];
}
return 0;
}
#include
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
int* p = &arr[0];
for (p = &arr[0]; p <= &arr[4]; p++)
{
*p = 0;
}
return 0;
}
:数组名表示的是数组首元素的地址.
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针
来源于:
https://blog.csdn.net/m0_58367586/article/details/128289887