Случайное значение в поле структуры - PullRequest
1 голос
/ 16 января 2020

Я пытаюсь выучить немного C, и я начал с простой программы колоды карт.

Карта представляет собой структуру, содержащую два целых числа для лица и масти. И я собираю колоду, распределяя 52 карты и тщательно изучая все oop.

card *Deck = (card*)malloc(sizeof(card) * 52);
for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck->face = j;
        Deck->suit = i;
        Deck += sizeof(card);
    }
}
Deck -= sizeof(card) * 52;
printDeck(Deck);

free(Deck);

. У меня есть функция printCard, которая принимает один указатель и печатает значения, и печатная колода. функция, которая вызывает printCard 52 раза. Если я печатаю карточки по мере их создания, все идет хорошо, но если я печатаю карточки после того, как все они были созданы по какой-то причине, я получаю сегментную ошибку на 6-й карточке. Я запустил gdb и заметил этот вывод:

Seven of Diamonds<br>
(null) of Diamonds<br>
Nine of Diamonds<br>

Остальная часть вывода нормальная. При проверке значения 6-й карты я получил:

(gdb) p c->face
$10 = 2675

Если я пропускаю 6-ю карту, вывод в порядке, и все работает так, как должно. Я новичок в C, но я не могу понять, как это значение было помещено в это поле в моем коде.

struct card{
    int face;
    int suit;
};

void printCard(card* c){
    printf("%s of %s\n", face_str[c->face], suit_str[c->suit]);
}

Редактировать:

Код PrintDeck:

До:

void printDeck(card* c){
    for(int i = 0; i < 52; i++){
        printCard(c);
        c += sizeof(card);
    }
}

После:

void printDeck(card* c){
    for(int i = 0; i < 52; i++){
        printCard(c);
        c++;
    }
}

printCard не изменилось:

void printCard(card* c){
    printf("%s of %s\n", face_str[c->face], suit_str[c->suit]);
}

Ответы [ 2 ]

6 голосов
/ 16 января 2020

Проблема в вашем коде заключается в следующей строке:

Deck += sizeof(card);

Здесь Deck - это card * (указатель на card). Если вы хотите продвинуться на одну позицию, арифметика указателя c сделает всю работу за вас, а выполнение Deck + 1 уже продвигает sizeof(card) вперед. Сложение или вычитание из указателя p всегда увеличивает sizeof(*p).

Правильный код будет:

Deck += 1;
// or 
Deck++;

Та же ошибка сделана после l oop, здесь:

Deck -= sizeof(card) * 52;

Что должно быть:

Deck -= 52;

Я новичок в C, но я не могу понять, как это значение было введено в это поле в моем code.

Если вы неправильно измените переменную Deck, вы получите доступ к памяти, размер которой превышает размер выделенного фрагмента (который равен sizeof(card) * 52). Это неопределенное поведение в C, и поэтому попытка напечатать такое значение может привести к печати случайных значений (если не хуже).


Я бы посоветовал вам полностью избегать изменения значения Deck и вместо этого индексировать его как массив:

card *Deck = malloc(sizeof(card) * 52);

for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck[i*13 + j]->face = j;
        Deck[i*13 + j]->suit = i;
    }
}

printDeck(Deck);
free(Deck);
5 голосов
/ 16 января 2020

Было бы интересно показать нам код функции printDeck.

Проблема, с которой вы столкнулись в данном коде: Deck += sizeof(card). Вы предполагали, что это переместит колоду sizeof(card) байт дальше. Но это не правильно. Когда Deck является указателем на card, увеличение Deck на единицу увеличивает его адрес на sizeof(card) байт.

Таким образом, ваш код должен быть

card *Deck = malloc(sizeof(card) * 52);
for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck->face = j;
        Deck->suit = i;
        Deck++;
    }
}
Deck -= 52;
printDeck(Deck);

free(Deck);

Возможно, вы сделали то же самое ошибка в printDeck.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...