【问题标题】:Are pointers and arrays any different in C?C中的指针和数组有什么不同吗?
【发布时间】:2009-06-28 04:39:32
【问题描述】:

我正在编写一个小型 C 程序来进行一些数字运算,它需要在函数之间传递数组。函数应该接受并返回指针,对吧?

例如,这个(我知道这可能不是最有效的):

int* reverse(int* l, int len) {
    int* reversed = malloc(sizeof(*reversed)*len);
    int i, j;
    for (i = 0, j = len-1; i < len; i++, j--) {
        reversed[j] = l[i];
    }
    return reversed;
}

我使用指针对吗?

【问题讨论】:

  • 您的示例看起来不错。数组和指针之间的区别这一更广泛的主题之前已在此处讨论过,例如stackoverflow.com/questions/660752/…
  • (这不符合答案)数组和指针代数的不同之处仅在于 sizeof(array_name) 返回 array_name 元素的计数,而不是数组的大小(以字节为单位)。

标签: c arrays pointers


【解决方案1】:

您的代码 sn-p 是正确的。但是,C 中的指针和数组确实是不同的。简单地说,“指向 T 类型的指针”与“类型 T 的数组”不同。

请查看 C Faq 讨论指针和数组以更好地理解这一点。

【讨论】:

  • 支持 C 常见问题解答 - 比您在 SO 上得到的答案更详细。
【解决方案2】:

C-FAQ: Arrays and Pointers 的链接已经给出,但C for Smarties: Arrays and Pointers 中也有详尽的解释。您可能需要先阅读“分析表达式”页面。

关于您的示例的几点需要更正:

  1. 使用int 而不是正确的size_t 来存储对象大小。
  2. 检查malloc()的返回值失败。

“解决”第二个问题的一种方法是让调用者决定输出的存储位置(也许调用者不想要或不需要新分配的数组):

int *reverse(int *out, int *l, size_t len) {
   size_t i, j;
   for (i = 0, j = len - 1; i < len; ++i, --j) {
     out[j] = l[i];
   }
   return out;
 }

【讨论】:

    【解决方案3】:

    从低层次的角度来看,数组是一个连续的内存块,通过该块的开头地址和偏移量访问,因此从抽象级别来看,它是一个指针。但是,从 C 语言的角度来看,数组类型不同于指针类型。基本上可以将数组分配给指针值,但它不是同一类型

    就你的功能而言,你做得很好。

    【讨论】:

    • 你的粗体声明需要解释。
    【解决方案4】:

    在迂腐理论中,数组和指针是不同的东西,因为数组指定了一个内存区域,因此数组的大小是其类型的一部分。所以有人说,当在该上下文中使用时,数组名称 衰减 为指针。 There's a detailed explanation in the C-FAQ.

    实际上它们是相同的,因为正式的a[i]*(a+i) 相同,因此编译器后端以完全相同的方式处理数组名称和指针。唯一值得担心的区别是

    void foo()
    {
       int a[5]; // allocates five words of space on the stack
       int *b;   // allocates *one* word of space on the stack (to hold the pointer)
    }
    

    您的代码 sn-p 很好。请注意释放您的函数malloc()s 在调用它的人中的内存。

    【讨论】:

      【解决方案5】:

      C 中的数组由指向第一个元素的指针表示和操作,例如

      int arr[50];
      int * ptr1 = arr;
      int * ptr2 = &arr[0];
      

      在本例中,ptr1 == ptr2,因为数组的第一个元素的地址和数组的基指针相同。

      所以您的基本示例是正确的,尽管我怀疑 malloc 应该是:

      int* reversed = malloc(sizeof(int)*len);
      

      【讨论】:

      • 这只是为了以防我想将其更改为其他内容(例如 long),这样我就不必更改两件事了。
      • 不,他的 malloc 从 C99 开始就很好(而且比你的更好)。
      • @[smcameron]: @reyjavikvi]:一种有趣的技术(我第一次没有注意到 * 前缀,对此感到抱歉!)。我是在 1982 年学习 C 的,自 1994 年以来就很少使用它,所以我从来没有读过 C99 规范(一定是错过了关于它的备忘录!;-))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2013-04-21
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多