当变量设置为索引参数时,会发生分段错误

Segmentation fault occurs when variable set to indexed parameter

本文关键字:分段 错误 设置 变量 索引 参数      更新时间:2024-09-28

我有一个扑克游戏,其中玩家的手牌数组和中间的牌数组作为参数传递给函数。在函数get_winner中,我可以循环并打印数组中的卡片(第 2 个和第 3 个用于循环),但是如果我将变量设置为数组的元素并打印它,则会出现分割错误。这是我代码的简化版本:

#include <iostream>
using std::cout, std::endl;
static const int num_players = 4;
static const char* SUITS[] = {"Hearts", "Diamonds", "Spades", "Clubs"};
static const char* VALUES[] = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
enum suit {hearts, diamonds, spades, clubs};
enum value {two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace};
struct card 
{
value v;
suit s;
};
std::ostream& operator<<(std::ostream &out, const card &c)
{
out << VALUES[c.v] << " of " << SUITS[c.s];
return out;
}
int get_winner(const card (*hand)[num_players][2], const card (*commun_cards)[5])
{
// this loop causes an error when printing the temp card variable  
for (int i = 0; i < 5; i++) {
auto temp_card = commun_cards[i];
cout << *temp_card << " " << (*temp_card).s << " " << (*temp_card).v << endl;
}
// these loops work fine and print the players' hands and community cards
for (int i = 0; i < num_players; i++) {
cout << (*hand)[i][0] << ", " << (*hand)[i][1] << endl;
}
for (int i = 0; i < 5; i++) {
cout << (*commun_cards)[i] << endl;
}
return 0;
}
int main()
{
card hands[num_players][2];
card commun_cards[5];
// fill hands and commun_cards with card structs
hands[0][0] = card {jack, spades};
hands[0][1] = card {nine, spades};
hands[1][0] = card {ace, clubs};
hands[1][1] = card {ace, hearts};
hands[2][0] = card {three, diamonds};
hands[2][1] = card {seven, spades};
hands[3][0] = card {eight, diamonds};
hands[3][1] = card {nine, clubs};
commun_cards[0] = card {five, clubs};
commun_cards[1] = card {king, hearts};
commun_cards[2] = card {queen, spades};
commun_cards[3] = card {two, spades};
commun_cards[4] = card {ace, hearts};
for (int i = 0; i < num_players; i++) {
cout << "Player " << i << " cards: " << hands[i][0] << ", " << hands[i][1] << endl;
}
cout << "nCommunity cards:n";
for (int i = 0; i < 5; i++) {
cout << commun_cards[i] << endl;
}
get_winner(&hands, &commun_cards);
}

函数的第一个循环错误地访问了commun_cards数组。它的第三个循环是正确访问数组。为什么你期望第一个循环需要访问元素与第三个循环有任何不同,因为它想将每个元素保存到一个变量?

由于您是通过指针传入每个数组的,因此必须先取消引用每个指针,然后才能索引到每个数组的元素中。您的第 2 个和第 3 个循环正在这样做。你的第一个循环不是。

您的第一个循环期望commun_cards[i]产生指向每个元素的指针,但这根本不是真的,这就是*temp_card崩溃的原因。如果你真的想要一个指向每个元素的指针,你需要改用这个:

auto *temp_card = &(*commun_cards)[i];
// alternatively:
// auto *temp_card = (*commun_cards) + i;
cout << *temp_card << " " << temp_card->s << " " << temp_card->v << endl;

否则,请使用对每个元素的引用而不是指针:

auto &temp_card = (*commun_cards)[i];
// alternatively:
// auto &temp_card = *((*commun_cards) + i);
cout << temp_card << " " << temp_card.s << " " << temp_card.v << endl;

如果您将函数更改为通过引用而不是指针接受数组(我强烈建议您这样做),那么该函数将变为:

int get_winner(const card (&hand)[num_players][2], const card (&commun_cards)[5])
{  
for (int i = 0; i < 5; i++) {
auto &temp_card = commun_cards[i];
cout << temp_card << " " << temp_card.s << " " << temp_card.v << endl;
}
for (int i = 0; i < num_players; i++) {
cout << hand[i][0] << ", " << hand[i][1] << endl;
}
for (int i = 0; i < 5; i++) {
cout << commun_cards[i] << endl;
}
return 0;
}
...
get_winner(hands, commun_cards);

这个循环应该是

// this loop causes an error when printing the temp card variable  
for (int i = 0; i < 5; i++) {
auto temp_card = (*commun_cards) + i; // change here
cout << *temp_card << " "<< temp_card->s << " " << temp_card->v << endl;  // change here
}

auto temp_card = &(*commun_cards)[i];是编写自动temp_card = (*commun_cards) + i;的另一种方式,temp_card->s是另一种编写(*temp_card).s的方式。

但是,您编写的代码通过传递指向数组的指针而不是指向数组元素的指针而变得不必要地复杂。数组的名称衰减为指向其第一个元素的指针,因此card commun_cards[5]变得card *commun_cardscard hand[num_players][2]变得card (*hand)[2]。这就是您通常将数组传递给函数的方式。

这是简化的整个功能

int get_winner(const card (*hand)[2], const card *commun_cards)
{
// this loop causes an error when printing the temp card variable  
for (int i = 0; i < 5; i++) {
auto temp_card = commun_cards[i];
cout << temp_card << " " << temp_card.s << " " << temp_card.v << endl;
}
// these loops work fine and print the players' hands and community cards
for (int i = 0; i < num_players; i++) {
cout << hand[i][0] << ", " << hand[i][1] << endl;
}
for (int i = 0; i < 5; i++) {
cout << commun_cards[i] << endl;
}
return 0;
}

然后

int main()
{
...
get_winner(hands, commun_cards);
}