【问题标题】:Why is this array notation illegal in C?为什么这个数组符号在 C 中是非法的?
【发布时间】:2012-01-17 08:57:56
【问题描述】:

如果可能的话:

#include <stdio.h>
#include <process.h>

#define SIZE 5

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

main()
{
    int myIntArray[5] = {1, 2, 3, 4, 5};

    PassingArray(myIntArray);

    system("PAUSE");
}

那为什么下面是非法的呢?

#include <stdio.h>
#include <process.h>

#define SIZE 5

int ReturningArray()[]
{
    int myIntArray[5] = {1, 2, 3, 4, 5};

    return myIntArray;
}

main()
{
    int myArray[] = ReturningArray();

    system("PAUSE");
}

【问题讨论】:

  • 您是否尝试从您的第二版ReturningArray 返回指向int 数组的指针?那个签名看起来不对..?
  • 当我传递一个整数数组时,我试图返回一个整数数组。
  • 返回int 数组的函数原型看起来类似于int* ReturningArray,但您必须自己管理malloc 并释放内存。我建议你看看cslibrary.stanford.edu/102/PointersAndMemory.pdf

标签: c arrays return


【解决方案1】:

你不能从函数中返回数组,但是你可以声明一个函数返回一个(C++ 中的引用)或指向数组的指针,如下所示:

int myIntArray[] = {1, 2, 3, 4, 5};

int (*ReturningArray())[sizeof(myIntArray)/sizeof(int)] {

    return &myIntArray;
}

【讨论】:

  • @Alf:我在编辑答案之前投了反对票,当时它是荒谬的。我现在已经删除了我的反对票。 (顺便说一句,我不同意反对投票的想法;如果您认为答案有用,您应该支持!)
  • Oli:我没有看到问题是关于 C(不是 C++)。但无论如何,已经添加了两个无法解释的反对票,所以我维持我的计数器。我认为那些通过投反对票来表达自己缺乏理解、感到沮丧或其他任何事情的人只是破坏性的,然后有点积极的赞成票是 In Order(TM)。
【解决方案2】:

这不起作用的原因有很多。

首先是语言禁止的——函数的返回类型不能是数组(也不能是函数)。

第二个是即使您被允许像您一样声明ReturningArray,您也永远无法在该函数中编写有效的return 语句 - 数组类型不是一元 &amp;sizeof 运算符的主题计算为指向数组第一个元素的指针,该元素不再具有数组类型。所以你实际上不能让return 看到一个数组。

第三,即使我们有一个返回数组类型的函数,也不能使用该返回值作为数组变量的初始化器——返回值将再次计算为指向数组第一个元素的指针:在这种情况下,指向int 的指针和指向int 的指针不是int 数组的合适初始化器。

【讨论】:

    【解决方案3】:

    PassingArray 是合法的,但它不传递数组。它传递一个指向数组第一个元素的指针。 void PassingArray(int arr[])void PassingArray(int *arr) 的一个令人困惑的同义词。您不能在 C 中按值传递数组。

    ReturningArray 是不允许的,你也不能在 C 中按值返回数组。通常的解决方法是返回一个包含数组的结构:

    typedef struct ReturnArray {
        int contents[5];
    } ReturnArray;
    
    ReturnArray ReturningArray()
    {
        ReturnArray x = {{1, 2, 3, 4, 5}};
        return x;
    }
    

    数组在 C 中是二等公民,它们不能通过值传递或返回的事实在历史上与它们不能通过赋值复制的事实有关。据我所知,其原因隐藏在 C 的早期开发中,早在它标准化之前,还没有完全决定数组如何工作。

    【讨论】:

      【解决方案4】:

      这段代码有几个问题。

      1. 您将括号放在错误的位置。而不是

        int ReturningArray()[]
        

        应该是

        int* ReturningArray()
        
      2. 您正在返回一个局部变量。局部变量只在函数执行过程中存在,之后会被移除。

      为了完成这项工作,您必须malloc int 数组并返回指向该数组的指针:

      #include <stdio.h>
      #include <malloc.h>
      
      #define SIZE 5
      
      int* ReturningArray()
      {
          int *myIntArray = (int *)malloc(SIZE * sizeof(int));
          myIntArray[0] = 1;
          myIntArray[1] = 2;
          myIntArray[2] = 3;
          myIntArray[3] = 4;
          myIntArray[4] = 5;
          return myIntArray;
      }
      
      int main(void)
      {
              int i;
              int* myArray = ReturningArray();
              for(i=0;i<SIZE;i++) { 
                      printf("%d\n", myArray[i]); 
              }
              free(myArray); // free the memory again
              system("PAUSE");
              return 0;
      }
      

      【讨论】:

      • 非常明确的答案......我喜欢你对另一个的评论。
      • “数组只是指向存储值的堆空间的指针。”。这不是真的。数组就是数组。可以有一个指向数组第一个元素的指针,并且在大多数上下文中使用数组的名称会产生该指针,但该指针不是数组。最后,你不能将数组作为参数传递,看起来传递数组的语法实际上传递了一个指针,但该指针仍然不是数组。
      • @SteveJessop:1. 确实,这是不正确的 - 2. 我在哪里说过可以将数组作为参数传递?
      • @halfdan:我认为您没有这样做,但是这种语法是使某些人(包括提问者)将数组与指针混淆的原因之一——事实上存在一些语法似乎传递了一个数组,但实际上传递了一个指针。
      【解决方案5】:

      您返回的不是 int,而是数组。这与&amp;myIntArray[0] 的值相同。 int ReturningArray()[] 不是有效的函数原型。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 2021-08-19
      • 2019-06-26
      相关资源
      最近更新 更多