上海黄浦区网站建设,专门做眼镜的网站,推荐好用的分销平台,怎么判断是不是外包公司目录 指针是什么?
指针和指针类型
指针-整数
指针的解引用
野指针
野指针成因
如何规避野指针 指针运算
指针- 整数
指针-指针
指针的关系运算
指针和数组
二级指针
指针数组
指针数组 模拟二维数组 指针是什么? 指针理解的2个要点: 1. 指针是内存中一个…目录 指针是什么?
指针和指针类型
指针-整数
指针的解引用
野指针
野指针成因
如何规避野指针 指针运算
指针- 整数
指针-指针
指针的关系运算
指针和数组
二级指针
指针数组
指针数组 模拟二维数组 指针是什么? 指针理解的2个要点: 1. 指针是内存中一个最小单元的编号也就是地址 2. 平时口语中说的指针通常指的是指针变量是用来存放内存地址的变量 总结:指针就是地址口语中说的指针通常指的是指针变量。 那我们就可以这样理解:
内存 指针变量
我们可以通过(取地址操作符)取出变量的内存其实地址把地址可以存放到一个变量中这个 变量就是指针变量
#include stdio.h
int main()
{
int a 10;//在内存中开辟一块空间
int *p a;
//这里我们对变量a取出它的地址可以使用操作符。
//a变量占用4个字节的空间这里是将a的4个字节的第一个字节的地址存放在p变量 中p就是一个之指针变量。
return 0;
} int a 10; //是向内存中的栈区空间申请4个字节的空间这四个字节用来存放10这个数值 int *p a;//这里我们对变量a取出它的地址可以使用操作符。 //a变量占用4个字节的空间这里是将a的4个字节的第一个字节的地址存放在p变量中p就是一个指针变量。 总结 指针变量用来存放地址的变量。(存放在指针中的值都被当成地址处理)。 那这里的问题是: 一个小的单元到底是多大? (1个字节) 如何编址? 经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。 对于32位的机器假设有32根地址线那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0); 那么32根地址线产生的地址就会是: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 ... 11111111 11111111 11111111 11111111 这里就有2的32次方个地址。
每个地址标识一个字节那我们就可以给
(2^32Byte 2^32/1024KB2^32/1024/1024MB2^32/1024/1024/1024GB 4GB)
4G的空闲进行编址。
同样的方法那64位机器如果给64根地址线那能编址多大空间自己计算。 这里我们就明白: 在32位的机器上地址是32个0或者1组成二进制序列那地址就得用4个字节的空间来存储所以一个指针变量的大小就应该是4个字节。 那如果在64位机器上如果有64个地址线那一个指针变量的大小是8个字节才能存放一个地址。 如图32位系统下 各个类型的指针都是4个字节 如图64位系统下 各个类型的指针都是8个字节 总结: 内存被划分成一个个内存单元每个内存单元的大小是1个字节 每个字节的内存单元都有一个编号这个编号就是地址地址在C语言中是指针 地址要存储的话存放在指针变量中 每个内存单元都有一个唯一的指针来标识 指针是用来存放地址的地址是唯一标示一块地址空间的。 指针的大小在32位平台是4个字节在64位平台是8个字节。 指针和指针类型 这里我们在讨论一下:指针的类型 我们都知道变量有不同的类型整形浮点型等。 那指针有没有类型呢? 准确的说:有的。 当有这样的代码:
int num 10;
p num;
要将num(num的地址)保存到p中我们知道p就是一个指针变量那它的类型是怎样的呢? 我们给指针变量相应的类型。
char *pc NULL;
int *pi NULL;
short *ps NULL;
long *pl NULL;
float *pf NULL;
double *pd NULL; 这里可以看到指针的定义方式是: type * 其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。 那指针类型的意义是什么?
指针-整数
#include stdio.h
//演示实例 int main() {int n 10;char *pc (char*)n;int *pi n;printf(%p\n, n);printf(%p\n, pc);printf(%p\n, pc1);printf(%p\n, pi);printf(%p\n, pi1);return 0;
} 总结指针的类型决定了指针向前和向后走一步有多大 int* 的指针1跳过4个字节 char* 的指针1跳过1个字节 short* 的指针1跳过2个字节 double* 的指针1跳过8个字节 指针的解引用
//演示实例
#include stdio.h
int main() {
int n 0x11223344;
char *pc (char *)n;
int *pi n;
*pc 0; //重点在调试的过程中观察内存的变化。
*pi 0; //重点在调试的过程中观察内存的变化。return 0;
} 指针类型决定了指针进行解引用操作的时候访问几个字节 char 1个字节 short 2个字节 int 4个字节 总结: 指针的类型决定了对指针解引用的时候有多大的权限(能操作几个字节)。比如: char* 的指针解引用就只能访问一个字节而 int* 的指针的解引用就能访问四个字节。 野指针 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的) 野指针成因
指针未初始化
#include stdio.h
int main() {
int *p;//局部变量指针未初始化默认为随机值 *p 20;
return 0;
}
指针越界访问
#include stdio.h
int main()
{int arr[10] {0};int *p arr;int i 0;for(i0; i11; i){//当指针指向的范围超出数组arr的范围时p就是野指针*(p) -1;}
return 0;
}指针指向的空间释放 这里放在动态内存开辟的时候详细说
如何规避野指针 指针初始化 ——如果明确指针应该指向哪里就初始化正确的地址 int a 10; int*p a; ——如果指针不知道初始化什么值为了安全初始化NULL int*p NULL; 小心指针越界 指针指向空间释放即使置NULL 避免返回局部变量的地址 指针使用之前检查有效性 初始化指针 在定义指针变量时立即将其初始化为 NULL 或有效的内存地址这样可以避免它成为野指针。 避免未初始化的指针 在使用指针之前确保为其分配了有效的内存空间。 可以使用动态内存分配函数如 malloc、calloc 等或者将指针指向有效的对象或数组。 避免释放后仍然使用指针 在释放了指针所指向的内存后不要再对其进行访问或引用。可以在释放后将指针设置为 NULL以避免意外使用。 合理使用指针 确保在使用指针之前检查其是否为 NULL。可以使用条件语句如 if或者断言来验证指针的有效性。 避免悬挂指针 当一个指针指向已经释放的内存时将其设置为 NULL以避免成为悬挂指针。 谨慎使用指针操作 在进行指针操作时要确保操作的对象是有效的并且不会越界访问。 #include stdio.h
int main(){int *p NULL;//....int a 10;p a;if(p ! NULL){
*p 20; }
return 0;
} 指针运算 指针- 整数 指针-指针 指针的关系运算 指针- 整数 //arr -- p //arr p //arri pi //*(arri) *(pi) arr[i] //*(arri) arr[i] //*(iarr) i[arr] ——方块仅仅只是操作符 //p指向的是数组首元素 //pi是数组中下标为i的元素的地址 //pi起始时跳过了i*sizeof(int)个字符 #define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针-整数;指针的关系运算
for (vp values[0]; vp values[N_VALUES];)
{*vp 0;
} 指针加减整数是指对指针进行偏移操作。当一个指针与一个整数相加或相减时编译器会根据指针所指向的数据类型来计算偏移量然后将指针移动到相应位置。 例如假设有一个指向整型数据的指针ptr可以使用以下方式进行偏移操作 ptr n将指针ptr向后移动n个单位每个单位的大小由指针所指向的数据类型决定。 ptr - n将指针ptr向前移动n个单位。 指针-指针 指针与指针之间的减法运算用于计算两个指针之间的偏移量。如果有两个指针ptr1和ptr2它们指向同一数组或同一内存块的不同位置可以使用以下方式计算它们之间的偏移量 ptr2 - ptr1计算ptr2相对于ptr1的偏移量结果将以单位为指针所指向的数据类型的大小表示。 指针的关系运算包括大于、小于、大于等于、小于等于、等于和不等于!等比较运算符。这些运算符用于比较两个指针的值比较结果基于指针所指向的内存地址。 //指针减去指针的前提两个指针指向同一块区域指针类型相同的
// 指针减去指针差值的绝对值得到的是指针之间的元素个数 模拟strlen 1.计数器 2.递归 int my_strlen(char *s)
{char *p s;while(*p ! \0 ) //八进制的0p;
}
return p-s; 指针的关系运算
for(vp values[N_VALUES]; vp values[0];)
{*--vp 0;
}
代码简化, 这将代码修改如下:
for(vp values[N_VALUES-1]; vp values[0];vp--)
{*vp 0;
} 实际在绝大部分的编译器上是可以顺利完成任务的然而我们还是应该避免这样写因为标准并不保证 它可行。 标准规定: 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较但是不允许与 指向第一个元素之前的那个内存位置的指针进行比较。 指针和数组 指针就是指针 指针变量存放地址指针变量的大小是4/8个字节 数组就是数组 存放一组数数组的大小是取决于元素的类型和个数 数组的数组名是数组首元素的地址地址是可以访问指针变量中 我们看一个例子:
#include stdio.h
int main() {int arr[10] {1,2,3,4,5,6,7,8,9,0};printf(%p\n, arr);printf(%p\n, arr[0]);return 0;
}
运行结果 可见数组名和数组首元素的地址是一样的。 结论:数组名表示的是数组首元素的地址。(2种情况除外数组章节讲解了) sizeof(数组名数组名单独放在sizeof内部数组名表示整个数组计算的是数组的大小单位是字节 数组名数组名表示整个数组取出的是数组的地址数组的地址和数组首元素的地址值是一样的但是类型和意义是不一样的。 那么这样写代码是可行的 int arr[10] {1,2,3,4,5,6,7,8,9,0};
int *p arr;//p存放的是数组首元素的地址 注前两个arr//arr[0])表示是数组首元素 1 跳过4个字节 arr表示数组 1 跳过40个字节 既然可以把数组名当成地址存放到一个指针中我们使用指针来访问一个就成为可能。
例如:
#include stdio.h
int main()
{
int arr[] {1,2,3,4,5,6,7,8,9,0}; int *p arr; //指针存放数组首元素的地址
int sz sizeof(arr)/sizeof(arr[0]);
for(i0; isz; i)
{printf(arr[%d] %p p%d %p\n, i, arr[i], i, pi);
return 0;
}
} 所以 pi 其实计算的是数组 arr 下标为i的地址。 那我们就可以直接通过指针来访问数组。 如下:
int main() {
int arr[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int *p arr; //指针存放数组首元素的地址
int sz sizeof(arr) / sizeof(arr[0]);
int i 0;for (i 0; isz; i){printf(%d , *(p i));}
return 0; }
二级指针 二级指针是指一个指针变量的值是另一个指针变量的地址也就是说这个指针变量存储的是另一个指针变量的地址。在C语言中可以通过使用二级指针来传递指针的地址以便在函数内部修改指针的值。 具体来说我们先来看一下一级指针的定义和使用。一级指针是最常见的指针它存储了一个对象的地址。通过解引用操作符(*)我们可以获取到该地址所对应的对象的值。 而二级指针则更进一步它存储了一个一级指针变量的地址。通过解引用操作符(**)我们可以获取到该一级指针所指向的对象的值。 为了更好地理解二级指针我们可以举个例子。 假设我们有一个整型变量x并且有两个指针p1和p2其中p1指向x的地址p2指向p1的地址。这样p2就成为了一个二级指针。 下面是一个简单的示例代码演示了如何声明和使用二级指针
#include stdio.hint main() {int x 10;int* p1 x;int** p2 p1;printf(x %d\n, x);printf(*p1 %d\n, *p1);printf(**p2 %d\n, **p2);return 0;
}
在上面的代码中我们首先声明了一个整型变量x并初始化为10。然后声明了一个一级指针p1并将其指向x的地址。接着声明了一个二级指针p2并将其指向p1的地址。
在打印输出部分我们使用解引用操作符()来获取到指针所指向的对象的值。可以看到通过p1我们可以获取到x的值通过**p2我们也可以获取到x的值。
二级指针在某些情况下非常有用例如在函数中传递指针的地址以便在函数内部修改指针的值。它也可以用于动态分配二维数组等复杂数据结构。 *ppa 通过对ppa中的地址进行解引用这样找到的是 pa *ppa 其实访问的就是 pa .
int b 20;
*ppa b;//等价于 pa b;
**ppa先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa 那找到的是 a .
**ppa 30; //等价于*pa 30; //等价于a 30;
指针数组
指针数组
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整形数组字符数组。
int arr1[5]; //整型数组
char arr2[6]; //字符数组 那指针数组是怎样的?
int* arr3[5];//是什么? arr3是一个数组有五个元素每个元素是一个整形指针。 整型指针数组 模拟二维数组 i 遍历指针数组arr // j 遍历数组arr1/2/3 模拟出二维数组的效果
文章转载自: http://www.morning.qfwfj.cn.gov.cn.qfwfj.cn http://www.morning.hqsnt.cn.gov.cn.hqsnt.cn http://www.morning.mgbcf.cn.gov.cn.mgbcf.cn http://www.morning.zdmrf.cn.gov.cn.zdmrf.cn http://www.morning.fncgw.cn.gov.cn.fncgw.cn http://www.morning.rlwgn.cn.gov.cn.rlwgn.cn http://www.morning.gsqw.cn.gov.cn.gsqw.cn http://www.morning.nrjr.cn.gov.cn.nrjr.cn http://www.morning.msfqt.cn.gov.cn.msfqt.cn http://www.morning.cwnqd.cn.gov.cn.cwnqd.cn http://www.morning.fhjnh.cn.gov.cn.fhjnh.cn http://www.morning.ltpph.cn.gov.cn.ltpph.cn http://www.morning.rlhh.cn.gov.cn.rlhh.cn http://www.morning.xcjwm.cn.gov.cn.xcjwm.cn http://www.morning.qnbgh.cn.gov.cn.qnbgh.cn http://www.morning.bhwll.cn.gov.cn.bhwll.cn http://www.morning.jqmqf.cn.gov.cn.jqmqf.cn http://www.morning.jqjnl.cn.gov.cn.jqjnl.cn http://www.morning.lsgsn.cn.gov.cn.lsgsn.cn http://www.morning.qfrsm.cn.gov.cn.qfrsm.cn http://www.morning.qxbsq.cn.gov.cn.qxbsq.cn http://www.morning.rcbdn.cn.gov.cn.rcbdn.cn http://www.morning.sqdjn.cn.gov.cn.sqdjn.cn http://www.morning.fgkwh.cn.gov.cn.fgkwh.cn http://www.morning.kqbjy.cn.gov.cn.kqbjy.cn http://www.morning.ggnkt.cn.gov.cn.ggnkt.cn http://www.morning.brfxt.cn.gov.cn.brfxt.cn http://www.morning.zcsch.cn.gov.cn.zcsch.cn http://www.morning.yqtry.cn.gov.cn.yqtry.cn http://www.morning.ptmsk.cn.gov.cn.ptmsk.cn http://www.morning.tbjb.cn.gov.cn.tbjb.cn http://www.morning.skqfx.cn.gov.cn.skqfx.cn http://www.morning.mftzm.cn.gov.cn.mftzm.cn http://www.morning.fmrrr.cn.gov.cn.fmrrr.cn http://www.morning.zpxwg.cn.gov.cn.zpxwg.cn http://www.morning.qngcq.cn.gov.cn.qngcq.cn http://www.morning.tfrmx.cn.gov.cn.tfrmx.cn http://www.morning.sqskm.cn.gov.cn.sqskm.cn http://www.morning.rxfbf.cn.gov.cn.rxfbf.cn http://www.morning.kpcky.cn.gov.cn.kpcky.cn http://www.morning.pjjkz.cn.gov.cn.pjjkz.cn http://www.morning.wjwfj.cn.gov.cn.wjwfj.cn http://www.morning.kpcxj.cn.gov.cn.kpcxj.cn http://www.morning.hprmg.cn.gov.cn.hprmg.cn http://www.morning.zqkr.cn.gov.cn.zqkr.cn http://www.morning.qxdrw.cn.gov.cn.qxdrw.cn http://www.morning.xpmhs.cn.gov.cn.xpmhs.cn http://www.morning.xlbtz.cn.gov.cn.xlbtz.cn http://www.morning.xwqxz.cn.gov.cn.xwqxz.cn http://www.morning.sphft.cn.gov.cn.sphft.cn http://www.morning.rqqkc.cn.gov.cn.rqqkc.cn http://www.morning.khlxd.cn.gov.cn.khlxd.cn http://www.morning.brlcj.cn.gov.cn.brlcj.cn http://www.morning.lmcrc.cn.gov.cn.lmcrc.cn http://www.morning.mnwsy.cn.gov.cn.mnwsy.cn http://www.morning.gnhsg.cn.gov.cn.gnhsg.cn http://www.morning.rjfr.cn.gov.cn.rjfr.cn http://www.morning.ldwxj.cn.gov.cn.ldwxj.cn http://www.morning.pgmyn.cn.gov.cn.pgmyn.cn http://www.morning.phzrq.cn.gov.cn.phzrq.cn http://www.morning.dnmzl.cn.gov.cn.dnmzl.cn http://www.morning.glncb.cn.gov.cn.glncb.cn http://www.morning.nlpbh.cn.gov.cn.nlpbh.cn http://www.morning.hlnrj.cn.gov.cn.hlnrj.cn http://www.morning.lfxcj.cn.gov.cn.lfxcj.cn http://www.morning.zzhqs.cn.gov.cn.zzhqs.cn http://www.morning.tgydf.cn.gov.cn.tgydf.cn http://www.morning.mbrbg.cn.gov.cn.mbrbg.cn http://www.morning.tsqpd.cn.gov.cn.tsqpd.cn http://www.morning.lgnbr.cn.gov.cn.lgnbr.cn http://www.morning.zlgth.cn.gov.cn.zlgth.cn http://www.morning.fbfnk.cn.gov.cn.fbfnk.cn http://www.morning.bpmnl.cn.gov.cn.bpmnl.cn http://www.morning.pynzj.cn.gov.cn.pynzj.cn http://www.morning.rshs.cn.gov.cn.rshs.cn http://www.morning.qqnh.cn.gov.cn.qqnh.cn http://www.morning.dkfb.cn.gov.cn.dkfb.cn http://www.morning.twmp.cn.gov.cn.twmp.cn http://www.morning.nqbpz.cn.gov.cn.nqbpz.cn http://www.morning.trplf.cn.gov.cn.trplf.cn