Передача строкового литерала в качестве параметра функции, определяемого как указатель
Я читаю главу о массивах и указателях в Кернигане и Ричи. Язык программирования C.
Они приводят пример:
/* strlen: return length of string s */
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
И затем скажите:
"Так как s
является указателем, то приращение его совершенно законно; s++
не влияет на символьную строку в функции, которая называется strlen
, а просто увеличивает приращение частной копии указателя strlens. звонки вроде
strlen("hello, world"); /* string constant */
strlen(array); /* char array[100]; */
strlen(ptr); /* char *ptr; */
все работают. "
Мне кажется, что я понимаю все это, кроме первого примера вызова: почему, или как, является строковым литералом "hello, world"
, рассматриваемым как char *s
? Как это указатель? Назначает ли функция этот строковый литерал как значение его локальной переменной *s
, а затем использует s
как имя/указатель массива?
Ответы
Ответ 1
Чтобы понять, как строка, подобная "Hello World" , преобразуется в указатель, важно понять, что строка представляет собой шестнадцатеричные данные, начинающиеся с адреса, и перемещение, пока не найдет NULL
Таким образом, каждая строковая константа, такая как "Hello World" , хранится в памяти где-то
Возможность:
0x10203040 : 0x48 [H]
0x10203041 : 0x65 [e]
0x10203042 : 0x6C [l]
0x10203043 : 0x6C [l]
0x10203044 : 0x6F [o]
0x10203045 : 0x20 [' ']
0x10203046 : 0x57 [W]
0x10203047 : 0x6F [o]
0x10203048 : 0x72 [r]
0x10203049 : 0x6C [l]
0x1020304A : 0x64 [d]
0x1020304B : 0x00 [\0]
Итак, когда эта функция вызывается с указанными выше значениями в памяти, [левая сторона - это адрес, за которым следует ":", а правая сторона - значение ascii символа]
int strlen(const char *s)
{
int n;
for (n = 0; *s != ′\0′; s++)
n++;
return n;
}
strlen("Hello World");
в то время, что передается в strlen
, это значение 0x10203040
, которое является адресом первого элемента массива символов.
Обратите внимание, что адрес передается по значению.. следовательно, strlen
имеет свою собственную копию адреса "Hello World" . начиная с n = 0
, после uptil я нахожу \0
в памяти, я увеличиваю n
, а также адрес в s
(который затем увеличивается до 0x10203041
) и так далее, пока не найдет \0
по адресу 0x1020304B
и возвращает длину строки.
Ответ 2
"hello, world"
представляет собой массив из char
(type is char[13]
). Значение массива char
в выражении является указателем на char
. Указатель указывает на первый элемент массива (т.е. Значение "hello, world"
равно &"hello, world"[0]
).
Ответ 3
Обратите внимание, что:
- Указатель - это (в основном) значение, указывающее на адрес памяти.
- Статическая строка типа
"hello, word"
хранится где-то в памяти
Таким образом, указатель может легко просто указать на статическую строку, как на любую другую (динамическую) структуру, которая хранится в памяти (например, массив символов). На других примерах нет никакой разницы.
Ответ 4
Назначает ли функция этот строковый литерал как значение его локальной переменной * s а затем использовать s в качестве имени/указателя массива?
Да
Ответ 5
Как сказано в первом абзаце той же страницы (Страница 99, K & R2):
"По определению, значение переменной или выражения массива типа адрес нулевого элемента массива. "
Значение "привет, мир" будет адресом "h".