c - 为什么不建议在 C 中使用指针进行数组访问
问题描述
我正在学习 C 编程,并且在线浏览了本教程,其中指出您应该始终尽可能地使用 [] 运算符而不是指针运算。
https://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html#dynamic
你可以使用指针算术(但一般不要)
考虑 C 中的以下代码
int *p_array;
p_array = (int *)malloc(sizeof(int)*50);
for(i=0; i < 50; i++) {
p_array[i] = 0;
}
使用像下面的代码这样的指针算术有什么区别(以及为什么不推荐)?
int *p_array;
p_array = (int *)malloc(sizeof(int)*50); // allocate 50 ints
int *dptr = p_array;
for(i=0; i < 50; i++) {
*dptr = 0;
dptr++;
}
在哪些情况下使用指针算法会导致软件出现问题?是不好的做法还是没有经验的工程师可以不注意?
解决方案
由于似乎对此感到困惑:
在过去,我们有 16 位 CPU,例如 8088、268 等。要制定地址,您必须加载段寄存器(16 位寄存器)和地址寄存器。如果访问数组,您可以将数组基址加载到段寄存器中,地址寄存器将是索引。这些平台的 C 编译器确实存在,但指针运算涉及检查地址是否溢出,并在必要时碰撞段寄存器(低效)平面寻址指针在硬件中根本不可能。
快进到 80386 现在我们有了一个完整的 32 位空间。硬件指针是可能的 索引 + 基址寻址会导致 1 个时钟周期的损失。虽然这些段也是 32 位的,因此即使您正在运行 32 位模式,也可以使用段加载数组以避免这种惩罚。368 还将段寄存器的数量增加了 2 个。(不知道为什么 Intel 认为这是个好主意)虽然周围仍然有很多 16 位代码
如今,段寄存器在 64 位模式下被禁用,Base+Index 寻址是免费的。
是否有任何平台可以让平面指针在硬件中胜过数组寻址?嗯,是。1979 年发布的摩托罗拉 68000 有一个平坦的 32 位地址空间,没有段,并且 Base + Index 寻址模式比立即寻址产生 8 个时钟周期的损失。因此,如果您正在编写 80 年代早期的 Sun 电台、Apple Lisa 等,这可能是相关的。
简而言之。如果需要数组,请使用数组。如果你想要一个指针,请使用指针。不要尝试聪明的编译器。将数组转换为指针的复杂代码极不可能提供任何好处,而且可能会更慢。
推荐阅读
- java - 需要一种即使应用程序重新启动也不会丢失的锁定机制(持久锁)?
- r - 为什么 SPSS 和 R 包、rstatix 和 DescTools 之间的部分 eta 平方值存在差异?
- angular - 为什么我在 Angular 应用程序中出现此错误?未捕获(承诺):NullInjectorError
- r - 来自重叠不均匀箱和计数的直方图/密度图
- ruby-on-rails - 手动生成设计密码并将记录与其他属性一起保存?
- python - 用数据框绘制 20 年的温度与月份的关系
- matlab - 如何将一维 matlab 数组代码转换为 Fortran 代码并获取值
- c# - 创建多个 xml 文件并将其导出为一个 zip 文件的最佳方法是什么
- json - React 在 PUT 上发送一个空的 JSON 对象
- routes - 部署到 Netlify 时,Sapper Svelte 路由不工作并且页面丢失