Передача строкового литерала в качестве параметра функции, определяемого как указатель

Я читаю главу о массивах и указателях в Кернигане и Ричи. Язык программирования 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".