c - 为什么不建议在 C 中使用指针进行数组访问

标签 c arrays pointers pointer-arithmetic

我正在学习 C 编程,我在网上看到了本教程,其中指出您应该始终尽可能多地使用 [] 运算符而不是指针算法。

https://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html#dynamic

you can use pointer arithmetic (but in general don't)



考虑下面的 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 位地址空间,没有段,并且基址 + 索引寻址模式比立即寻址会导致 8 个时钟周期的损失。因此,如果您正在编写 80 年代早期的 Sun 站、Apple Lisa 等程序,这可能是相关的。

简而言之。如果需要数组,请使用数组。如果你想要一个指针,使用一个指针。不要尝试聪明的编译器。将数组转换为指针的复杂代码极不可能提供任何好处,并且可能会更慢。

关于c - 为什么不建议在 C 中使用指针进行数组访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59692578/

相关文章:

c++ - 智能指针和复制构造函数

c++ - 方法返回模板类 C++

C 程序崩溃,不知道为什么?

c - 字符串序列及其实现

c# - 随机化一系列餐厅

c - 在 C 中使用指针时为 "lvalue required as left operand of assignment"

c - printf 有问题或者什么的

c - 将字符读入有限的缓冲区大小

ios - 使用对象的属性作为字典的键从对象数组创建字典?

c - 如何从函数返回数组到main