Понимание массива строковых указателей символов
Я пытаюсь понять результаты, которые я получаю при обращении к указателю "p". Я разместил комментарии в строке, заявив, что, по моему мнению, происходит.
#include <stdio.h>
main()
{
char *words[] = { "hello", "world" };
char **p = words; // p is now pointing to words[0]?
++p; // p now points to "world"
printf("%s\n", *p); // Prints the character string 'world', pointed to by p
printf("%c\n", *p[0]); // Returns 'w'
printf("%c\n", *p[1]); // Should return 'o'? Returns garbage
printf("%c\n", *++p[0]); // Returns 'o'?
}
Я понимаю, что после:
char ** p = слова;
Этот p теперь указывает на первый символ, на который указывают слова [0], т. Е. На "h" в "привет". Затем после:
++ р
Теперьp указывает на первый символ, на который указывает указатель на слова [1], то есть на "w" в "мире".
Результаты, достижения:
world
w
<blank space>
o
Если *p[0] возвращает символ 'w'. Тогда почему *p[1] возвращает мусор? Я пытаюсь понять, как содержимое памяти, на которое указывают указатели в * словах, организовано в памяти, где p указывает после каждого вызова.
Обновить
Изменяя следующие строки:
printf("%d\n", *p[0]);
printf("%d\n", *p[1]);
printf("%d\n", *++p[0]);
Результаты сейчас:
119 // 'w'
1 // 'SOH' -- Start of heading
111 // 'o'
Теперь, что именно является символом SOH, в этом контексте?
2 ответа
Есть недоразумение.
Расположение памяти после:
char *words[] = { "hello", "world" };
будет выглядеть примерно так:
words[0] words[1]
| |
v v
+-----------+-----------+
| ptr1 | ptr2 |
+-----------+-----------+
ptr1
+---+---+---+---+---+------+
| h | e | l | l | o | '\0' |
+---+---+---+---+---+------+
ptr2
+---+---+---+---+---+------+
| w | o | r | l | d | '\0' |
+---+---+---+---+---+------+
Вы сказали:
char **p = words; // p is now pointing to world[0]?
Если бы вы имели в виду words[0]
тогда вы правы.
Вы также сказали,
Тот
p
теперь указывает на первый символ, на который указываетwords[0]
Это не правильно. Тип p
является char**
, Ты мог бы сказать *p
указывает на первый символ, на который указывает words[0]
,
Что касается вывода программы...
У вас есть строка:
++p;
Эта строка меняется p
так что это указывает на words[1]
,
Линия
printf("%c\n", *p); // Should return 'w'? But returns garbage
является причиной неопределенного поведения, так как тип *p
это не int
это представляет char
, Тип *p
является char*
не char
,
Линия
printf("%c\n", *p[0]); // Returns 'w'
печать w
поскольку p[0]
равно ptr2
, Как вы можете видеть из макета памяти, *ptr2
оценивает 'w'
, Следовательно, вы получаете w
на выходе.
Линия
printf("%c\n", *p[1]); // Should return 'o'? Returns garbage
также является причиной неопределенного поведения.
Из-за приоритета оператора, *p[1]
эквивалентно *(p[1])
, что эквивалентно *(*(p+1))
, поскольку p
уже указывает на words[1]
, (p+1)
указывает на неверную память.
Вы должны использовать предупреждение, чтобы показать вам основную ошибку
a.c:10:5: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat]
*p
это указатель на символ Пытаться:
printf("%s\n", *p);
printf("%c\n", *p[1]);
Вот p[1]
может быть третьим элементом words
поскольку нет третьего элемента, вы читаете значение мусора.
За ++p[0]
p[0]
указывает на "world"
с ++
эта точка "orld"
затем с *
вы печатаете первый char
так o
,
Чтобы отменить понимание указателя вы можете использовать print
с %p
чтобы увидеть ваш точный адрес.