При экспериментировании с методами для перехода по массиву строк в 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