为了账号安全,请及时绑定邮箱和手机立即绑定

传递2D结构数组

/ 猿问

传递2D结构数组

C
忽然笑 2019-11-20 10:45:24

我从数组中处理卡类型结构。


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

我正在使用2D阵列。卡类型结构的数组的数组


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); ^


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


查看完整描述

3 回答

?
一只萌萌小番薯

将数组作为函数参数传递时,最重要的事情是:不能将数组传递给函数。


话虽如此,请仔细阅读以下内容。(int为简单起见,我将使用它,但是当然您也可以使用其他类型。)


但是您可以将“指向第一个元素的指针”传递给数组。幸运的是,C自动进行了转换。更,对于所有但三个例外(sizeof,_Alignof,&运营商),C自动转换一个阵列的名称这样的指针。通常将其称为“数组衰减到指向第一个元素的指针”。


但是这种衰减不是递归的。因此,如果将2D数组传递给函数,则它将衰减为指向1D数组的指针:


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;

(我只使用了常量1并2为尺寸编号;当然,您可以使用所需的尺寸。)


如果要传递可变长度的数组(VLA,_variable长度数组),则必须将除最外面的维之外的所有维传递给函数:


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

但更好的检查方法是通过所有尺寸:


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


查看完整回答
反对 回复 2019-11-20
?
慕姐829404

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


好的,我们走吧-


假设我们有一个函数set_up_array,该函数将指向2D数组的指针作为参数。


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;

        }

    }

}

那可能会让你吓坏了,但是可以和我在一起。


现在,想象一下您要作为表传递的2D数组。它有行,然后有列。您将如何转到此类表格中的下一个元素?好了,您有了元素的索引,就可以找到索引,对吧?这就是我们在这里所做的。

首先,我将说明将数组类型转换为int *的原因。这很简单。每当我们进行指针数学运算时,C编译器都会尝试简化我们的工作(就像真正的芽...),因此,我们无需添加指针的地址,而只需添加元素的数量,然后基于C编译器会自动找出我们想要的地址。现在,这就是问题所在,C编译器通过找出指针所指向的类型的大小来找出问题所在。因此,为了使我们的生活变得简单,并使C编译器满意,我们将其转换为int *,这意味着从现在开始,我们添加的任何内容都会像int *一样添加到初始地址中s。现在让我们回到表的比喻。我们知道行号和列号。

在此处输入图片说明

您可能要记住的一件事是,该图像的列和行标签颠倒了


为了使我们的生活更加简单,让我们切换到笛卡尔视图(带有x和ay坐标的图形视图)。假设x是水平的,而y是垂直的。然后,我们可以将错误记录为:

array[y][x]

这意味着我们想要的x*row_size + y元素是元素。我们基本上可以将其添加到函数中的指针,然后像对其完成一样取消引用,就在那里使用了i和j。


查看完整回答
反对 回复 2019-11-20
?
喵喔喔

如果您非常仔细地阅读了我的答案(我想我在答案中写道),您会发现您错了。如果缺少特定信息,请随时发表评论(适当时)。如果您不了解其中的基本知识(无冒犯),请了解堆栈溢出不是教程站点。在这种情况下,您应该读一本上帝(比K&R还新)的C书。

查看完整回答
反对 回复 2019-11-20

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信