Можно заставить код работать (компилировать, запускать без сбоев и создавать понятный, объяснимый ответ), но вам нужна структура, отличная от выбранной.Например:
#include <stdio.h>
struct my_structure
{
char *i;
};
#define EXPR(x) #x, x
int main(void)
{
char strings[][10] = { { "Winter" }, { "Bash" }, { "Is" }, { "Here" } };
struct my_structure variables[] = { { strings[0] }, { strings[1] }, { strings[2] }, { strings[3] } };
struct my_structure *p = variables;
printf("%10s: %s\n", EXPR(++p->i));
printf("%10s: %s\n", EXPR(p++->i));
printf("%10s: %d\n", EXPR(*p->i++));
printf("%10s: %d\n", EXPR(*p->i++));
printf("%10s: %d\n", EXPR((*p->i)++));
printf("%10s: %d\n", EXPR(*p++->i));
return 0;
}
, который генерирует вывод:
++p->i: inter
p++->i: inter
*p->i++: 66
*p->i++: 97
(*p->i)++: 115
*p++->i: 116
Макрос EXPR
просто позволяет мне не повторять выражения в коде, и все же получить обе строкиform и значение в вызове printf()
.
Когда все начинается, p->i
указывает на строку "Winter"
.
++p->i: inter
- предварительное увеличениеуказатель p->i
, поэтому он указывает на i
из Winter
. p++->i: inter
- после увеличения указатель p
(для указания на "Bash"
), но результатТо же, что и раньше, поскольку приращение вступает в силу после использования p->i
. *p->i++: 66
- после увеличения указатель p->i
(таким образом, он указывает на a
в Bash
) и сообщаетзначение, на которое указывает до приращения, которое составляет B
(66 в ASCII). *p->i++: 97
- то же выражение, но указатель указывает на a
(97) перед приращением и на s
после увеличения. (*p->i)++: 115
- после увеличения буквы, на которую указывает p->i
, сообщая s
, но изменяявведите t
. *p++->i: 116
- постинкремент p
, чтобы он указывал на строку «In», сообщая при этом t
(116).
Вот альтернатива с большим количеством инструментов:
#include <stdio.h>
struct my_structure
{
char *i;
};
#define EXPR(x) #x, x
int main(void)
{
char strings[][10] = { { "Winter" }, { "Bash" }, { "Is" }, { "Here" } };
struct my_structure variables[] = { { strings[0] }, { strings[1] }, { strings[2] }, { strings[3] } };
struct my_structure *p = variables;
for (size_t i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
printf("strings[%zu] = [%s]\n", i, strings[i]);
for (size_t i = 0; i < sizeof(variables)/sizeof(variables[0]); i++)
printf("variables[%zu].i = [%s]\n", i, variables[i].i);
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %s\n", EXPR(++p->i));
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %s\n", EXPR(p++->i));
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %d\n", EXPR(*p->i++));
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %d\n", EXPR(*p->i++));
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %d\n", EXPR((*p->i)++));
printf("%10s: %s\n", EXPR(p->i));
printf("%10s: %d\n", EXPR(*p++->i));
printf("%10s: %s\n", EXPR(p->i));
for (size_t i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
printf("strings[%zu] = [%s]\n", i, strings[i]);
for (size_t i = 0; i < sizeof(variables)/sizeof(variables[0]); i++)
printf("variables[%zu].i = [%s]\n", i, variables[i].i);
return 0;
}
и его вывод:
strings[0] = [Winter]
strings[1] = [Bash]
strings[2] = [Is]
strings[3] = [Here]
variables[0].i = [Winter]
variables[1].i = [Bash]
variables[2].i = [Is]
variables[3].i = [Here]
p->i: Winter
++p->i: inter
p->i: inter
p++->i: inter
p->i: Bash
*p->i++: 66
p->i: ash
*p->i++: 97
p->i: sh
(*p->i)++: 115
p->i: th
*p++->i: 116
p->i: Is
strings[0] = [Winter]
strings[1] = [Bath]
strings[2] = [Is]
strings[3] = [Here]
variables[0].i = [inter]
variables[1].i = [th]
variables[2].i = [Is]
variables[3].i = [Here]
Поиграйте с вариантами этой схемы (например, с дополнительными скобками), чтобы убедиться, что вы понимаете, что происходит.