赞
踩
在理解指针之前我们需要知道计算机中的内存分配。
将内存比作学校,内存单元就好比⼀个个教室,⼀个字节空间里面能放8个比特位,就好比教室里只能存在8个人,每个人是⼀个比特位。每个内存单元也都有⼀个编号(这个编号就相当于教室的门牌号),有了这个内存单元的编号,CPU就可以快速找到这个内存空间(教室)。生活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也称为地址。C语⾔中给地址起了新的名字叫:指针。
#include <stdio.h>
int main()
{
int a = 10;
int* pa = &a;//取出a的地址并存储到指针变量pa中
return 0;
}
#include <stdio.h>
int main()
{
int a = 10;
int * pa = &a;
return 0;
}
#include <stdio.h>
int main()
{
int a = 100;
int* pa = &a;
*pa = 0;
printf("%d\n", a);//输出0
return 0;
}
#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(double*));
return 0;
}
结论:
代码1:
#include <stdio.h>
int main()
{
int n = 0x11223344;
int *pi = &n;
*pi = 0;
return 0;
}
代码1:
#include <stdio.h>
int main()
{
int n = 0x11223344;
char* pc = (char*)&n;
*pc = 0;
return 0;
}
结论:
int main()
{
int n = 10;
char* pc = (char*)&n;
int* pi = &n;
printf("&n= %p\n", &n);
printf("pc= %p\n", pc);
printf("pc+1 =%p\n", pc + 1);
printf("pi= %p\n", pi);
printf("pi+1= %p\n", pi + 1);
return 0;
}
结论:
#include <stdio.h>
int main()
{
int m = 0;
m = 20;//m是可以修改的
const int n = 0;
n = 20;//n是不能被修改的
return 0;
}
上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n进行修改,就不符合语法规则,就报错,致使没法直接修改n。
但是如果我们绕过n,使用n的地址,去修改n就能做到了,虽然这样做是在打破语法规则。
int main()
{
const int n = 0;
printf("n = %d\n", n);
int* p = &n;
*p = 20;
printf("n = %d\n", n);
return 0;
}
int* p//没有const修饰
int const *p//const 放在*的左边做修饰等价于const int *p
int* const p//const 放在*的右边做修饰
int const * const p //const 放在*的左右两边做修饰
#include <stdio.h> //代码1 - 测试⽆const修饰的情况 void test1() { int n = 10; int m = 20; int* p = &n; *p = 20;//ok p = &m; //ok } //代码2 - 测试const放在*的左边情况 void test2() { int n = 10; int m = 20; const int* p = &n; *p = 20;//err p = &m; //ok } //代码3 - 测试const放在*的右边情况 void test3() { int n = 10; int m = 20; int* const p = &n; *p = 20; //ok p = &m; //err } //代码4 - 测试*的左右两边都有const void test4() { int n = 10; int m = 20; int const* const p = &n; *p = 20; //err p = &m; //err } int main() { //测试⽆const修饰的情况 test1(); //测试const放在*的左边情况 test2(); //测试const放在*的右边情况 test3(); //测试*的左右两边都有const test4(); return 0; }
const修饰指针变量的时候的结论:
#include <stdio.h>
//指针+- 整数
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = &arr[0];
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));//p+i 这里就是指针+整数
}
return 0;
}
#include <stdio.h>
//指针 - 指针
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p1 = &arr[0];
int* p2 = &arr[6];
printf("%d\n", p1 - p2);//-6
printf("%d\n", p2 - p1);//6
return 0;
}
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = &arr[0];
int sz = sizeof(arr) / sizeof(arr[0]);
while (p < arr + sz) //指针的大小比较
{
printf("%d ", *p);//打印数组所有的元素
p++;
}
return 0;
}
//1.指针未初始化
#include <stdio.h>
int main()
{
int* p;//局部变量指针未初始化,没有明确的指向,默认为随机值
*p = 20;//非法访问内存了,p就是野指针
//随机将p指向的对象改变是非常危险的,这是错误的做法
return 0;
}
//2.指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = &arr[0];
int i = 0;
for (i = 0; i <= 11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
//我们没有权限访问及修改,这片空间
*(p++) = i;
}
return 0;
}
//3.返回局部变量的地址(生命周期结束后使用)
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
//p中存着a的地址,a已经还给操作系统了,p不能使用这块空间,p就是野指针
//但是内存里的这块空间还在,只是不属于当前程序,没有使用着块空间的使用权限
printf("%d\n", *p);//通过非法的地址,如果这块空间没有被使用(覆盖),还能找到10,但是不属于我们。
return 0;
}
代码如下:
#include <stdio.h>
int main()
{
int num = 10;
int* p1 = #
int* p2 = NULL;
return 0;
}
#include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = &arr[0]; int i = 0; for (i = 0; i < 10; i++) { *(p++) = i; } //此时p已经越界了,可以把p置为NULL p = NULL; //下次使⽤的时候,判断p不为NULL的时候再使⽤ //... p = &arr[0];//重新让p获得地址 if (p != NULL) //判断 { //... } return 0; }
assert(p != NULL);
初识指针到这里就结束了,日后还会更新指针的奥秘(2.0)以及(3.0)等等。不要错过了哦。
觉得我写的不错的,可以给个三连哦,您的支持将是我对日后更新最大的动力,感谢啦!!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。