传递结构的二维数组
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
、&
运算符)之外,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;
(我只是使用常量1
和2
对尺寸进行编号;当然你可以使用你想要的尺寸。)
如果你想传递一个可变长度的数组(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 书籍。以上是关于传递结构的二维数组的主要内容,如果未能解决你的问题,请参考以下文章