Насколько я понимаю, следующий код работает так:
char* cptr = "Hello World";
«Hello World» находится в разделе .rodata
памяти программы. Строковый литерал "Hello World"
возвращает указатель на базовый адрес строки или адрес первого элемента в так называемом «массиве», поскольку символы располагаются в памяти последовательно, это будет «H». Это моя маленькая диаграмма, когда я визуализирую, как строковый литерал сохраняется в памяти:
0x4 : 'H'
0x5 : 'e'
0x6 : 'l'
0x6 : 'l'
0x7 : 'o'
0x8 : ' '
0x9 : 'W'
0xa : 'o'
0xb : 'r'
0xc : 'l'
0xd : 'd'
0xe : '\0'
Таким образом, объявление выше становится:
char* cptr = 0x4;
Теперь cptr указывает на строковый литерал. Я просто придумываю адреса.
0xa1 : 0x4
Теперь, как этот код работает?
char cString[] = "Hello World";
Я предполагаю, что, как и в предыдущей ситуации, "Hello World"
также деградирует до адреса «H» и 0x4.
char cString[] = 0x4;
Я читаю =
как перегруженный оператор присваивания, когда он используется с инициализацией массива символов. Насколько я понимаю, при инициализации только C-строки он копирует символ за символом, начиная с заданного базового адреса, в C-строку, пока не встретит «\ 0» в качестве последнего скопированного символа. Он также выделяет достаточно памяти для всех символов. Поскольку перегруженные операторы на самом деле являются просто функциями, я предполагаю, что их внутренняя реализация аналогична strcpy()
.
Я хотел бы, чтобы один из более опытных программистов на C подтвердил мои предположения о том, как работает этот код. Это моя визуализация C-строки после того, как в нее скопированы символы из строкового литерала:
0xb4 : 'H'
0xb5 : 'e'
0xb6 : 'l'
0xb6 : 'l'
0xb7 : 'o'
0xb8 : ' '
0xb9 : 'W'
0xba : 'o'
0xbb : 'r'
0xbc : 'l'
0xbd : 'd'
0xbe : '\0'
Опять же, адреса произвольные, дело в том, что C-строка в стеке отлична от строкового литерала в секции .rodata
в памяти.
Что я пытаюсь сделать? Я пытаюсь использовать указатель char для временного хранения базового адреса строкового литерала и использовать тот же указатель char (базовый адрес строкового литерала) для инициализации C-строки.
char* cptr = "Hello World";
char cString[] = cptr;
Я предполагаю, что "Hello World"
соответствует базовому адресу 0x4
. Таким образом, этот код должен выглядеть так:
char* cptr = 0x4;
char cString[] = 0x4;
Я предполагаю, что он не должен отличаться от char cString[] = "Hello World";
, поскольку «Hello World» оценивается по его базовому адресу, и именно это хранится в указателе char!
Однако gcc выдает ошибку:
error: invalid initializer
char cString[] = cptr;
^
- Почему вы не можете использовать указатель char в качестве временного заполнителя для хранения базового адреса строкового литерала?
- Как работает этот код? Верны ли мои предположения?
- Возвращает ли использование строкового литерала в коде базовый адрес в «массив», где символы хранятся в памяти?
char cString[] = "Hello World"
не требует никаких указателей — символcString
оказывается адресом массива из 12 символов, инициализированного символами из Hello World. - person Steve Summit   schedule 20.06.2018