Массив строки в C, странное поведение - PullRequest
0 голосов
/ 07 октября 2018

Я пытаюсь решить головоломку с играми кодов.
Это простой код:

#include <stdio.h>    
int main(void) {
    char *hashTable[3];
    for (int i = 0; i < 3; i++) 
    {
        char EXT[101]; 
        char MT[501];
        scanf("%s%s", EXT, MT); fgetc(stdin);
        hashTable[i]= MT;
    }
    printf("%s\n",hashTable[0]);
    printf("%s\n",hashTable[1]);
    printf("%s\n",hashTable[2]);
}

Если я, например, наберу: aa \ nbb \ ncc \ n
Выходные данныебудет: "ccc" вместо "abc".Почему последние значения "c" перезаписывают hashTable [0] и hashTable [1].Вместо этого я получил правильный код:

#include <stdio.h>    
int main(void) {
    char *hashTable[3];
    char *hashTable2[3];
    hashTable2[0]="a";
    hashTable2[1]="b";
    hashTable2[2]="c";
    for (int i = 0; i < 3; i++) 
    {
        hashTable[i]= hashTable2[i];
    }
    printf("%s ",hashTable[0]);
    printf("%s ",hashTable[1]);
    printf("%s ",hashTable[2]);
}

Ответы [ 3 ]

0 голосов
/ 07 октября 2018

Во-первых, EXT & MT являются локальными в области действия цикла for, и они не существуют вне этой области.Это UB.

Во-вторых, вы присваиваете один и тот же адрес массива всем элементам вашего char * массива.Когда вы выходите из цикла, этот адрес больше не действителен.

вам нужно выделить память для всех элементов:

for (int i = 0; i < 3; i++) 
{
    hashTable[i]= malloc( /*some size*/);
    if(hashTable[i])
        scanf("%s", hashTable[i]); /* just an example */
}
0 голосов
/ 07 октября 2018

Массивы EXT и MT являются локальными для блока, содержащего for;они перестают существовать в конце }.

Внутри блока вы помещаете их адрес в hashtable.

Когда вы пытаетесь напечатать их содержимое (помните, что к этому времени массивы прекратилисьсуществовать) вы вызываете неопределенное поведение .

0 голосов
/ 07 октября 2018

Вы назначаете указатель на ту же область памяти, поэтому будет отображаться последнее введенное значение.

MT - это 501 байт зарезервированной памяти, вы помещаете туда введенное пользователем значение, а затем назначаете адрес MTхеш-таблица [i].Затем вы помещаете новое значение в те же 501 байт, перезаписывая предыдущее.

Например, предположим, что MT [501] имеет начальный физический адрес 1000, поэтому каждый элемент hashTable будет равен 1000, а точката же память.Вот почему у вас напечатано то же значение.

Кроме того, поскольку вы объявили переменную как "auto", она будет размещена в стеке.После окончания выполнения блока указатель стека будет скорректирован, чтобы эта память могла быть повторно использована при следующем выделении.У вас нет других выделений между концом блока и вашим отпечатком, поэтому он не был перезаписан.В противном случае он будет перезаписан при следующем выделении памяти.

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