Понимание массива строковых указателей символов

Я пытаюсь понять результаты, которые я получаю при обращении к указателю "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 чтобы увидеть ваш точный адрес.

Другие вопросы по тегам