一
#includeint main() { int a = 0, b = 0; int* pa = &a; char* pc; char* pb =&b; printf("%dn", sizeof(pa));//4 printf("%dn", sizeof(pb));//4 printf("%dn", sizeof(pc));//4 求变量占内存的大小 return 0; }
~1字节等于8位
~指针就是指地址地址大小都为4个字节(32位系统——32根物理线地址线——2^32——
00000000000000000000000000000000——4个字节)
~1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
~进制转换
~调试 窗口 内存(0x代表16进制)
二 指针的类型
1.指针类型决定了:指针解引用的权限有多大,比如整形为4个字节,则整形指针变量可改变4个字节的内存
int main()
{
//int* pa;
//char* pc;
//float* pf;
//printf("%dn", sizeof(pa));//4
//printf("%dn", sizeof(pc));//4
//printf("%dn", sizeof(pf));//4
int a = 0x11223344;//一个数如果16进制,就代表16个0
int* pa = &a;//int------------------>4个字节
*pa = 0;//对a赋值 00 00 00 00
int a = 0x11223344;//一个数如果16进制,就代表16个0
char* pa = &a;//----------------1个字节
*pa = 0;//00 33 22 11
return 0;
}
2.指针类型决定了:指针走一步(+1)能走多远,即指针的步长
int main()
{
int arr[10] = { 0 };
int* pa = arr;
char* pc = arr;
printf("%pn", pa);//地址最后两位 44
printf("%pn", pa+1);//48
printf("%pn", pc);//44
printf("%pn", pc + 1);//45
return 0;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* pa = arr;//arr[0]的地址(四个单元格中的第一个单元格)
重点:int类型,步长为四
//一个单元格代表一个字节
for (int i = 0; i < 10; i++)
{
//*(pa + i) = 1;//解引用后拿到的是一个值————>int arr[10] = { 1,1,1,1,1,1,1,1,1,1 };
pa + i;//每一个数组元素的四个单元格中的第一个单元格
}
return 0;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char* pa = arr;//
for (int i = 0; i < 10; i++)
{
//*(pa + i) = 1;
pa + i;//一个单元格一个单元格的跳,就改变了三个数
}
return 0;
}
三.野指针(指针指向的位置是不可知的情况)
1.指针未初始化
int main()
{
int* p;
*p = 20;
return 0;
}
2.指针访问越界
int main()
{
int arr[10] = 0;
int* p = arr;
int i = 0;
for (i = 0; i <= 10; i++)//int a[10];
{
*p = i;
p = p + 1;
}
}
3.指针指向空的空间(指针指向的空间被释放)
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();//a的地址
*p = 20;
return 0;
}
四.定义不知道指针指向的地址是哪里
int main()
{
int* p = NULL;//定义空指针
int a = 1;
p = &a;
return 0;
}
五.如何避免野指针
1.指针初始化
int* p = NULL; -- > 不知道指针指向的地址是哪里 int* p = &a; -- > 知道指针指向的地址是哪里
2.小心指针越界
3.指针指向空间被释放时,要及时赋值NULL
4.指针要避免返回(return)局部变量的地址
5.指针使用之前,要检查有效性
int* p = NULL;
if (p != NULL)//
{
}
六.指针的运算
a.指针+-整数
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 9; i >= 0; i--)
{
p = p + i;
}
return 0;
}
b.指针减指针(指针减指针的结果为两个指针之间的元素个数)
指针不能加指针
int main()
{
int arr[10] = { 0 };
int i = &arr[9] - &arr[0];//不算a[9] 1~10中有9个数(不包含10)
printf("%dn", i);
return 0;
}
c.指针的关系运算(>,<,==,!=)
int a[10] = { 0 };
int* i = NULL;
for (i = &a[9]; i > &a[0];)
{
//*(--i) = 0;有无括号都可
i = i - 1;//得到a[8]的地址
*i = 0;//得到a[8]的值
}
for (i = &a[8]; i >= a[0]; i--)
{
*i = 0;
}
int a[10] = { 0 };
int* i = NULL;
for (i = &a[10]; i > &a[0];)//可执行
{
//*(--i) = 0;有无括号都可
i = i - 1;//得到a[8]的地址
*i = 0;//得到a[8]的值
}
for (i = &a[9]; i >= &a[0]; i--)//不可执行
{
*i = 0;
标准规定:允许指向数组元素的指针与指向数组最后一个后面的那个内存装置的指针进行比较,
但是,不允许与指向第一个元素之间的内存位置指针进行比较
七.指针与数组
数组名表示的是数组首元素的地址(两种情况除外)
1.sizeof(arr)—— > 整个数组占内存的大小,sizeof(arr) / sizeof(arr[0]);
2. & arr-- > 整个数组的地址
int arr[10] = { 0 };
sizeof((arr + 1) - arr) = 4;
sizeof((&arr + 1) - &arr) = 40;
int main()
{
int arr[10] = { 0 };
int* p = arr;
arr[2] == *(p + 2);//正确
*(p + 2) == *(arr + 2);//arr和p是首元素的地址 正确
arr[2] == *(arr + 2);//正确
}
void bubble_sort(int arr1[], int sz1);//arr1[]得到的是地址
{
int i = 0;
for (i = 0; i < sz1 - 1; i++)
{
int j = 0;
for (j = 0; j < sz1 - i - 1; j++)
{
if (arr1[j]==arr[j] > arr1[j + 1])
{
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);//数组长度
bubble_sort(arr, sz);
八.二级指针
指针,一个变量,也需要地址存放,那么存放指针地址值的变量,叫做二级指针
int main()
{
int a = 0;
int* pa = &a;
int** ppa = &pa;
*ppa = &a;//*ppa==pa --> pa = &a
**ppa = 20;
a = 20;
return 0;
}
九.指针数组:
int arr[],char arr1[],本质都是数组
指针数组的本质也是数组,指针数组里面的元素是什么类型——>指针
int* arr[5];



