我从数组中处理卡片类型结构。
struct card deck[DECKSIZE]; //The deck is an array of cards structures
我正在使用2D数组。一组卡片类型结构数组
struct card allHands[hands][cards];
我使用此函数将deck和数组作为指针传递给数组的参数。我还改变了甲板指针的位置,以模拟卡片在传递给玩家时丢失卡片。
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(甲板,所有手,手,牌); ^
注意:预期'struct card **'但参数类型为'struct card()[(sizetype)(cards)]' void dealHands(struct card [],struct card [],int,int); ^
当我需要在一个函数中调用它们时,我总是搞砸指针和数组。所以我不确定我的逻辑在哪里有缺陷。我在哪里传递地址而不是值,反之亦然?答案 0 :(得分:7)
将数组作为函数参数传递时最重要的是:无法将数组传递给函数。
说,仔细阅读以下内容。 (为简单起见,我将使用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]
。注意括号!您使用哪种语法基本上是个人偏好。我更喜欢所有维度的数组语法,因为它更清楚地记录了意图。
除最外层尺寸外,您必须始终传递所有尺寸。这仅用于文档而不是必需的(参见下面的示例)。
在函数内部,使用普通的index-operator:
int t, i; // index variable for ouTer, Inner
a[t][i];
请注意,这可以应用于更高维度的数组。对于1D阵列,这实际上也适用。只需删除内部维度:
int a[1];
衰败到
int *a;
(我只使用常量1
和2
来对尺寸进行编号;当然,您可以使用所需的尺寸。)
如果要传递长度可变的数组(VLA,_variable length array),则必须将除最外层维度以外的所有维度传递给函数:
f(int inner, a[][inner]);
但更好的检查等是通过所有维度:
f(int outer, int inner, a[outer][inner]);
答案 1 :(得分:-2)
所有这一切可能都有点难以理解,但一旦你试验它就很容易。你看,你永远不能将整个数组作为参数传递(我的意思是你可以通过传递每一个元素,但这不是重点)。数组基本上是一种表格。如果它是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和y坐标)。让我们说x是水平的,而y是垂直的。然后我们可以将arrray写为
array[y][x]
这意味着我们想要的元素是x*row_size + y
元素。
我们基本上可以添加到我们函数中的指针,并取消引用它,就像它已经完成,就在那里,我们使用了i和j。