Экспериментируя с методами пошагового массив строк в C, я разработал следующую небольшую программу:У меня три петли над массивом элементов (char *) в 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
является символом массива из-указателя к. Таким образом, когда s
установлено на family2[0]
, у нас есть (char*)
, указывающий на «отец». Поэтому принятие &s
должно дать нам эквивалент family2
, указывая на первый элемент family2
после ожидаемого распада указателя. Почему же тогда *(&s + 1)
указывает на следующий элемент, как и ожидалось?
Большое спасибо,
lifecrisis
EDIT - обновление и извлеченные уроки:
Следующий список представляет собой краткое изложение всех соответствующих фактов и интерпретаций, которые объясняют, почему третий цикл не работает, как первые два.
s
представляет собой отдельную переменную, содержащую копию значения (указатель к полукокса) от переменнойfamily2[0]
. I.e., эти два эквивалентных значения расположены в SEPARATE местах в памяти.family2[0]
доfamily2[3]
являются смежными элементами памяти, аs
не имеет присутствия в этом пространстве, хотя он содержит то же значение, которое хранится вfamily2[0]
в начале нашего цикла.- Эти первые два факта означают, что
&s
и&family2[0]
НЕ равны. Таким образом, добавление одного к&s
вернет указатель на неизвестные/неопределенные данные, тогда как добавление одного к&family2[0]
даст вам&family2[1]
, если требуется. - Кроме того, шаг обновления в третьем цикле for фактически не приводит к тому, что s будет выполняться вперед в памяти на каждой итерации. Это связано с тем, что
&s
является постоянным во всех итерациях нашего цикла. Это является причиной наблюдаемого бесконечного цикла.
Благодаря КАЖДОМУ на их помощь!
lifecrisis
Что такое 'string'? C не имеет строкового типа. – Olaf
Обратите внимание на typedef в верхней части блока кода! Благодаря! – lifecrisis
А, да! Таким образом, применяется другое предупреждение: ** Никогда еще ** 'typedef' указатель! Он запутывает код, спам пространства имен и делает код, отличный от кода, сложным, если не невозможным. – Olaf