将数组传递给函数时使用的正确模式

时间:2017-12-31 12:44:02

标签: c arrays pointers

我目前正在阅读understanding pointers in c,我在该部分讨论了将数组传递给函数的问题。在所有最好使用的波纹管模式中,为什么? ,它与优化有什么关系吗?

#include <stdio.h>


void passAsPointerWithSize(int * arr, int size) {
  for ( int i = 0; i < size; i++ ) {
    printf("%d\n", arr[i]);
  }
}


void passAsPointerWithoutSize(int * arr) {
  while ( *arr ) {
    printf("%d\n", *arr);
    arr++;
  }
}

void passWithoutPointerWithSize( int arr [] , int size) {
  for ( int i = 0; i <= size; i++ ) {
    printf("%d\n", arr[i]);
  }
}



void passWithoutPointerUsingWhile(int arr []) {
  int i = 1;
  while ( arr[i] ) {
    printf("%d\n", arr[i++]);
  }
}


int main() {
  int size = 5;
  int arr[5] = { 1, 2, 3, 4 , 5};
  passAsPointerWithSize(arr, size);
  passAsPointerWithoutSize(arr);
  passWithoutPointerWithSize(arr, size);
  passWithoutPointerUsingWhile(arr);
}

我用-std=gnu11 -O3

编译了它

3 个答案:

答案 0 :(得分:4)

在函数参数的上下文中,int arr []int *arr相同,因为当数组作为函数参数传递给函数参数时,衰减成指针到第一个元素

以下声明:

void foo(int * arr, int size);

相当于:

void foo(int arr[], int size);

当涉及到是否需​​要size参数的问题时,您需要它来确定数组的长度,除非:

  • 数组中存储了一个特殊值,用作数组末尾的指示符(被调用方负责检查此指标)。
  • 调用者已知数组的长度。

否则,您怎么可能知道数组包含多少元素?

  

最好使用的所有波纹管模式以及为什么?

考虑到以上几点,您唯一可以选择的是使用int *语法或int []语法作为函数参数。

尽管两者都是等价的(如上所述),但有些人可能会争辩说使用int *可能表明最多只有一个元素,而int []可能表明存在至少一个元素并且可能有不止一个。

  

它与优化有什么关系吗?

不,或者至少,不是直接,是否需要size参数实际上是调用者是否知道数组的大小,或者是否可以通过存储的阵列末尾指标。

答案 1 :(得分:3)

首先看哪一个是正确的! (根据你发布的内容)

void passAsPointerWithSize(int * arr, int size) {
  for ( int i = 0; i < size; i++ ) {
    printf("%d\n", arr[i]);
  }
}

这是调用未定义行为。

使用while的人不会停止,除非他们获得值为0的元素。如果数组没有0&s 39?然后它将访问超出内存的方式(这是这里的情况)。也许这个回声回到了字符串过去常常用零标记的时候,无论如何,这都是不好的做法。

另一个for循环是循环,直到index<=size访问数组索引超出范围index = size,同样,未定义的行为。

现在回到你的问题..

在将1D数组传递给函数 的上下文中,语法func(int arr[],..)func(int* arr,...)相同。数组作为指针传递 - 与指定签名的方式无关。

循环? - 这只是一个选择问题。

错别字和其他东西......

错别字是其中一个函数中的<=i=1初始化。你不想打印第0个元素吗?好i=1然后你开始循环 - 它错过了0-th元素。

编译器在传递数组时会处理指向数组第一个元素的指针,无论你如何编写它,所以形式并不重要

我如何知道传递的数组的大小?

在任何情况下 - 当您将数组作为指针传递给函数时 - 除非您有一些标记数组末尾的占位符,否则无法知道数组的长度。如果情况并非如此,那么您显然必须知道它的长度 - 这是您在函数中传递名为size的参数时所执行的操作。

可读性+选择+ ......

将它写为arr[]可用于表达当我们处理该指针时它是一个数组的含义。您可以浏览代码并了解它作为参数获得的内容以及可能执行的操作。有人可能会说,评论仍然可以达到这个目的 - 这就是选择进入图片的地方。

答案 2 :(得分:1)

是的,其中一些不起作用(例如,条件* arr是什么意思?你试图带回空终止的字符串吗?不要!)

但是,实际上最快的一个(除非我在实践中没有看到一些疯狂的编译器优化)如果你不关心顺序是向后迭代

void passAsPointerWithSize(int *arr, int size) {
  for ( int i = size - 1; i > 0; i-- ) {
    printf("%d\n", arr[i]);
  }
}

这是因为它在每个循环中节省了整个CPU时钟周期,因为在减少i(i--)之后,比较为零(i> 0)的答案已经存储在寄存器中