传递结构的二维数组

Posted

技术标签:

【中文标题】传递结构的二维数组【英文标题】:Passing a 2D array of structs 【发布时间】:2016-06-07 11:50:04 【问题描述】:

我正在处理数组中的卡片类型结构。

struct card deck[DECKSIZE];  //The deck is an array of cards structures

我使用的是二维数组。卡片类型结构数组的数组

struct card allHands[hands][cards];

我使用这个函数将卡片组和数组作为带有数组参数的指针传递。我还更改了牌组指针的位置,以模拟牌组在传递给玩家时丢失卡片。

void dealHands(struct card *deck, struct card **handArray, int hands, int cards)

    int players;
    int cardCount;
    int passCard = 0;
    struct card * thisDeck;

    thisDeck = deck;

    for(players = 0; players < hands; players++)
        for(cardCount = 0; cardCount < cards; cardCount++)
            handArray[players][cardCount] = thisDeck[passCard];
            passCard++;
           
    
    deck = (deck + passCard);   
   

我用 c 编程已经很久了,所以我想这就是你做原型的方式吗?

    void dealHands(struct card[], struct card*[], int, int);

这就像我如何实现该功能的主要框架。

int main(int argc, char *argv[])

    /* Declare and initialize variables  */

    int hands = atoi(argv[HANDSINPUT]);  //How many players 
    int cards = atoi(argv[CARDSINPUT]);  //How many cards per hand  
    struct card deck[DECKSIZE];  //The deck is an array of cards structures

    struct card allHands[hands][cards];

    //Builds the deck
    //Shuffles deck with a RNG and swapping every card

    int players;
    int cardCount;
    int passCard = 0;   


    dealHands(deck, allHands, hands, cards);



我在编译过程中得到以下 2 个语句

警告:从不兼容的指针类型传递“dealHands”的参数 2 [默认启用] dealHands(deck, allHands, Hands, Cards); ^

注意:预期为“struct card **”,但参数类型为“struct card ()[(sizetype)(cards)]” void dealHands(struct card[], struct card[], int, int); ^

当我需要在函数中调用指针和数组时,我总是搞砸。所以我不确定我的逻辑在哪里有缺陷。我在哪里传递地址而不是值,反之亦然?

【问题讨论】:

struct card ** 无法获取二维数组。指针不是数组!正如警告所暗示的那样,对参数使用正确的声明。 @Olaf 就是这样。我不记得如何正确声明它。如果它的 struct card *handArray[] 或 struct card handArray[][] 或其他东西。我似乎找不到它:/ 你注意到我发布了一个相当全面的答案,不是吗? 不,对不起,我的错。 @Olaf 我还不习惯这个界面。 请拨打tour。与往常一样,您应该知道如何使用 SO。 【参考方案1】:

将数组作为函数参数传递时最重要的一点是:您不能将数组传递给函数或从函数传递数组

说了这么多,请仔细阅读以下内容。 (为简单起见,我将使用int,当然您也可以使用其他类型。)

但是您可以传递数组的“指向第一个元素的指针”。幸运的是,C 会自动进行转换。更重要的是,除了三个例外(sizeof_Alignof&amp; 运算符)之外,C 会自动将数组的名称转换为这样的指针。这通常被称为“数组衰减到指向第一个元素的指针”。

但是这种衰减不是递归的。因此,如果您将二维数组传递给函数,它会衰减为指向一维数组的指针:

int a[1][2];    // 1 = outer dimension, 2 = inner

当传递给函数时

void f(int a[1][2]);

变成

int (*a)[2]   // pointer to array of inner dimension

也可以显式使用指针语法

void f(int (*a)[2]);

a 的类型在所有情况下都是 int (*)[2]。注意括号!您使用哪种语法基本上是个人喜好。我确实更喜欢所有维度的数组语法,因为它更清楚地记录了意图。

除了最外面的维度外,您始终必须传递所有尺寸。这仅用于文档,不是必需的(请参见下面的示例)。

在函数内部,你使用普通的索引操作符:

int t, i;    // index variable for ouTer, Inner
a[t][i];

请注意,这可以应用于更高维度的数组。对于一维数组,这实际上也适用。只需删除内部维度:

int a[1];

衰减到

int *a;

(我只是使用常量12对尺寸进行编号;当然你可以使用你想要的尺寸。)


如果你想传递一个可变长度的数组(VLA,_可变长度数组),你必须把除了最外层的所有维度都传递给函数:

f(int inner, a[][inner]);

但更好的检查等是通过所有维度:

f(int outer, int inner, a[outer][inner]);

【讨论】:

谢谢。它编译成功。原型以 struct card[][MAXCARDS] 结尾,函数是 struct card handArray[hands][cards] 我对 dealCards 函数有一个小问题。但是现在我重新阅读了答案,我意识到了我的错误。非常感谢您提供的信息。【参考方案2】:

所有这些可能有点难以理解,但是一旦你尝试了它就很容易了。你看,你永远不能将整个数组作为参数传递(我的意思是你可以通过传递每一个元素,但这不是重点)。数组基本上是一种表。如果它是一维的,那么你有一行框。如果它是 2D 的,则您有一个盒子表。如果它是 3D,则您有一个 cub(e/oid) 盒子。不过,您可以做的是利用数字在内存中的布局方式并使用指针算法。这很简单。

好的,我们走吧-

假设我们有一个函数,set_up_array,它接受一个指向二维数组的指针作为参数。

void set_up_array(int **array, int row_size, int column_size)
    for(int i = 0; i < row_size; i++)
        for(int j = 0; j < column_size; j++)
            *((int*)array + i*row_size + j) = i + j + k;
        
    

这可能会让你大吃一惊,但请留在我这里好吗。

现在,想象一下您作为表格传递的二维数组。它有行,然后有列。您将如何转到此类表中的下一个元素?好吧,你有你的元素的索引,你会发现它,对吧?这正是我们在这里所做的。 我将首先解释我们将数组类型转换为 int* 的原因。这很简单。每当我们进行指针数学运算时,C 编译器都会尝试简化我们的工作(就像一个真正的芽......),所以我们不是将地址添加到指针,而是简单地添加元素的数量,并基于此,C编译器会自动找出我们想要的地址。现在,问题来了,C 编译器通过找出指针指向的类型的大小来解决这个问题。所以,为了让我们的生活变得简单,也为了让 C 编译器开心,我们将它转​​换成一个 int*,这意味着,从这里开始,我们添加的任何内容都将像使用 int* 一样添加到初始地址s。 现在让我们回到表格类比。我们知道行号和列号。 您可能要记住的一件事是,此图像的列和行标签颠倒了

为了让我们的生活更简单,让我们切换到笛卡尔视图(一种图形视图,带有 x 和 y 坐标)。假设 x 是水平的,而 y 是垂直的。然后我们可以将数组写为 array[y][x] 这意味着我们想要的元素是x*row_size + y 元素。 我们基本上可以将其添加到函数中的指针,并取消引用它,就像它已经完成一样,就在那里,我们使用了 i 和 j。

【讨论】:

int ** 不是二维数组!它是一个指向指针的指针——非常不同的数据结构(只是碰巧有相同的语法来访问元素)。与图片中的布局不符。 好吧...,哇,我认为这是很长一段时间的情况,因为二维数组可以分解为数组数组,因此,指向指针的指针.能详细点吗? 重复一遍:数组不是指针。请参阅我的答案以正确传递任意维数的数组。也 only 强制转换 iff 1) 它们确实是必需的 2) 你了解 所有 含义并且 3) 接受它们完全. @Olaf 呃...那么问题出在哪里?我知道数组是一个连续的数据块。而通过它是不可能的。事实上,即使使用它也是不可能的。我们需要指针运算,以及指向第一个元素的指针。这就是为什么我说二维数组应该衰减为指向指针的指针(指向数组的指针,然后衰减为指向指针的指针) 最后一次重复:如果您非常仔细阅读我的答案(我想我在答案中写过),您会发现哪里错了。如果缺少特定信息,请随时发表评论(在适当的情况下)。如果您不了解那里的基础知识 - 无意冒犯 - ,请理解堆栈溢出不是教程站点。在这种情况下,您应该阅读一本神(并且比 K&R 更新的)C 书籍。

以上是关于传递结构的二维数组的主要内容,如果未能解决你的问题,请参考以下文章

二维数组地址传递的问题,求帮助~

使用 c++/vC++ 将结构数组和二维数组传递给函数

C语言函数传递二维数组

《程序设计基础》实验题目1 二维数组 冒泡排序

opencl核函数怎么传二维数组实参

C语言中 指针做函数参数传递二维数组