При экспериментировании с методами для перехода по массиву строк в C я разработал следующую небольшую программу:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main() {
char *family1[4] = {"father", "mother", "son", NULL};
string family2[4] = {"father", "mother", "son", NULL};
/* Loop #1: Using a simple pointer to step through "family1". */
for (char **p = family1; *p != NULL; p++) {
printf("%s\n", *p);
}
putchar('\n');
/* Loop #2: Using the typedef for clarity and stepping through
* family2. */
for (string *s = family2; *s != NULL; s++) {
printf("%s\n", *s);
}
putchar('\n');
/* Loop #3: Again, we use the pointer, but with a unique increment
* step in our for loop. This fails to work. Why? */
for (string s = family2[0]; s != NULL; s = *(&s + 1)) {
printf("%s\n", s);
}
}
Мой конкретный вопрос касается отказа Loop # 3. При прохождении через отладчик Loops # 1 и # 2 завершаются успешно, но последний цикл выходит из строя по неизвестной причине. Я бы не спросил об этом здесь, кроме факта, что показывает мне, что у меня есть некоторые критические недоразумения относительно "&". Оператор.
Мой вопрос (и текущее понимание) таков: family2
- это массив-указатель на char. Таким образом, когда s
установлено на family2[0]
, мы имеем a (char*)
, указывающий на "отец". Поэтому принятие &s
должно дать нам эквивалент family2
, указывая на первый элемент family2
после ожидаемого распада указателя. Почему же тогда нет,
*(&s + 1)
указывает на следующий элемент, как ожидалось?
Большое спасибо,
lifecrisis
EDIT - обновление и извлеченные уроки:
Следующий список представляет собой резюме всех соответствующих фактов и интерпретаций, которые объясняют, почему третий цикл не работает, как первые два.
-
s
- это отдельная переменная, содержащая копию значения (указатель-to- char) из переменнойfamily2[0]
. I.e., эти два эквивалентных значения расположены в SEPARATE местах в памяти. -
family2[0]
доfamily2[3]
являются смежными элементами памяти, аs
не имеет присутствия в этом пространстве, хотя оно содержит то же значение, которое хранится вfamily2[0]
в начале нашего цикла. - Эти первые два факта означают, что
&s
и&family2[0]
НЕ равны. Таким образом, добавление одного в&s
вернет указатель на неизвестные /undefined данные, тогда как добавление одного в&family2[0]
даст вам&family2[1]
, если требуется. - Кроме того, шаг обновления в третьем цикле for фактически не приводит к тому, что s будет выполняться вперед в памяти на каждой итерации. Это связано с тем, что
&s
является постоянным во всех итерациях нашего цикла. Это является причиной наблюдаемого бесконечного цикла.
Благодаря КАЖДОМУ за их помощь!
lifecrisis