Массив строк и указателей работает для каждого символа в массиве - PullRequest
0 голосов
/ 22 февраля 2020

В коде C

char a[][10]={"AIZEN","GINJO","ISHIDA","PERNIDA","GRIMMJOW"};
char (*ptr)[10]=a;
while(*ptr!='\0'){
    printf("%s\n",*ptr);
    ptr++;
}

L oop выполняется 31 раз, что равно количеству символов в массиве a. Когда я изменяю строку 3 как

while((*ptr)[10]!='\0'){

L oop запускается 5 раз, печатая имена в массиве. Почему [10] необходимо в этом l oop здесь? Даже если я использую индекс (while(a[i]!='\0')) вместо указателей, я должен сделать то же самое, чтобы получить правильный вывод.

Это то, что я имею в виду, массив выглядит так: enter image description here Так что я думаю [5] автоматически станет \0, а l oop закончится.

Ответы [ 3 ]

3 голосов
/ 22 февраля 2020

Есть две проблемы:

  1. Тест while (*ptr != '\0') {...} не делает то, что вы думаете, делает. Причина, по которой код компилируется, заключается в том, что, к сожалению, символьная константа '\0' также может считаться константой нулевого указателя (*). Возможно, вы имели в виду сравнение символа с while (**ptr != '\0') {...}.

  2. Массив char a[][10]={...} будет иметь столько элементов, сколько вы объявите. Если вы хотите прекратить его, вам нужно добавить дополнительный элемент "" в конце. Таким образом, дополнительный пустой элемент будет обнаружен с помощью условия l oop.

Доступ к внешнему массиву во время выполнения кода является неопределенным поведением, и может произойти все что угодно (включая цикл 31 times).

(*) Стандарт использует следующую формулировку: «Целочисленное константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя». Символы в C являются целыми числами, и поэтому '\0' является целочисленным константным выражением со значением 0. Хорошие компиляторы все равно должны предупреждать об этом случае, так как это распространенная ошибка (например, gcc -Wall будет предупреждать явно о возможной отсутствующей разыменовке).

3 голосов
/ 22 февраля 2020

Ну, ваша программа неверна.

ptr - это указатель на массив (из 10 символов). Итак, *ptr - это массив из 10 символов. Поэтому не имеет смысла сравнивать *ptr с \0, так как *ptr не будет нулевым.

При выполнении сравнения *ptr сначала укажет на «AIZEN», после увеличения его будет указывать на "GINJO" и так далее. Для каждого приращения ptr, *ptr будет просто увеличиваться на 10. После 5 приращений вы получаете доступ вне массива, когда вы делаете printf("%s\n",*ptr);. Это неопределенное поведение, и может произойти все, что угодно.

Попытка этого

while(*ptr != '\0'){
    printf("%s\n",*ptr);
    printf("%p\n",(void*)ptr);
    printf("%p\n",(void*)*ptr);
    ptr++;
}

может привести к выводу, подобному этому

AIZEN
0x7ffd162228c0
0x7ffd162228c0
GINJO
0x7ffd162228ca
0x7ffd162228ca
ISHIDA
0x7ffd162228d4
0x7ffd162228d4
PERNIDA
0x7ffd162228de
0x7ffd162228de
GRIMMJOW
0x7ffd162228e8
0x7ffd162228e8

0x7ffd162228f2
0x7ffd162228f2

0x7ffd162228fc
0x7ffd162228fc

0x7ffd16222906
0x7ffd16222906
P@
0x7ffd16222910
0x7ffd16222910
nɜ
0x7ffd1622291a
0x7ffd1622291a

Здесь вы видите, как увеличиваются указатели и что Оператор print генерирует все виды странных вещей (из-за неопределенного поведения, но это также могло привести к сбою программы).

Вы можете изменить свою программу следующим образом:

int main(void) {
    char a[][10]={"AIZEN","GINJO","ISHIDA","PERNIDA","GRIMMJOW", ""};  // Notice
                                                                       // the empty string
                                                                       // to stop
                                                                       // the loop
    char (*ptr)[10]=a;
    while(**ptr !='\0'){       // Notice **
        printf("%s\n",*ptr);
        printf("%p\n",(void*)ptr);
        ptr++;
    }
    return 0;
}

То есть: 1) добавьте пустую строку в массив и 2) разыменуйте указатель, чтобы проверить NUL (т. е. завершение строки)

Также обратите внимание, что во втором примере (*ptr)[10]!='\0' также не имеет смысла. Вы получаете доступ к 11-му элементу в массиве (он же строка), но массив состоит всего из 10 элементов.

0 голосов
/ 22 февраля 2020

См. Это,

#include<stdio.h>

int main()
{
    char a[][10]={"AIZEN","GINJO","ISHIDA","PERNIDA","GRIMMJOW"};
    char (*ptr)[10]=a;
    for(int i=0;i<5;i++,ptr++)
        printf("%s\n",ptr);
    return 0;
}

В вашем коде

   while(*ptr!='\0');

ptr не обнуляется

или не изменяется

char a[][10]={"AIZEN","GINJO","ISHIDA","PERNIDA","GRIMMJOW",""}; //string literels are NULL terminated by the compiler

while(**ptr!='\0');

Примечание:

 *ptr refer to initial address of string

 **ptr refer to address of character in the string
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...