Почему последний индекс массива строк ничего не печатает в C? - PullRequest
0 голосов
/ 29 января 2019

Мне любопытно, почему последний элемент в моем массиве размером 29 равен 27, а не 28?Почему появляется пробел, когда я пытаюсь распечатать объект на 28 месте?s должен быть последним объектом на 28 месте нет?

#include <stdio.h>

int main(void) {
    char strArray[] = { "Jonsnow from Game of Thrones" };
    int lastElem = sizeof(strArray);

    printf("%s\n", strArray);
    printf("Size of array is: %d\n", sizeof(strArray));
    printf("first array value: %c \n", strArray[0]);
    printf("last array value: %c \n", strArray[lastElem - 1]);
    printf("last array value: %c \n", strArray[lastElem - 2]);

    return 0;
}

Вывод:

Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

Ответы [ 5 ]

0 голосов
/ 29 января 2019

Последний байт в строке C - это нулевой терминатор, байт со значением 0, также записанный как '\0'.strArray - это массив char, инициализированный из строковой константы C, его размер точно соответствует размеру инициализатора, включая нулевой байт, следовательно, strArray[lastElem-1] - это нулевой байт '\0'.

ВыводНулевой байт с форматом printf %c должен работать нормально, нулевой байт записывается в stdout, но возможно, что ваш терминал игнорирует такие байты и выдает выложенный вами вывод.Вы можете попытаться перенаправить вывод вашей программы в файл и проверить этот файл с помощью шестнадцатеричного редактора, чтобы увидеть, действительно ли он содержит нулевой байт перед новой строкой.

Я получаю такое же поведение на моем MacBook с ОС/ X:

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte
Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

Но вот двоичный дамп вывода программы:

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte | od -bc
0000000   112 157 156 163 156 157 167 040 146 162 157 155 040 107 141 155
           J   o   n   s   n   o   w       f   r   o   m       G   a   m
0000020   145 040 157 146 040 124 150 162 157 156 145 163 012 123 151 172
           e       o   f       T   h   r   o   n   e   s  \n   S   i   z
0000040   145 040 157 146 040 141 162 162 141 171 040 151 163 072 040 062
           e       o   f       a   r   r   a   y       i   s   :       2
0000060   071 012 146 151 162 163 164 040 141 162 162 141 171 040 166 141
           9  \n   f   i   r   s   t       a   r   r   a   y       v   a
0000100   154 165 145 072 040 112 040 012 154 141 163 164 040 141 162 162
           l   u   e   :       J      \n   l   a   s   t       a   r   r
0000120   141 171 040 166 141 154 165 145 072 040 000 040 012 154 141 163
           a   y       v   a   l   u   e   :      \0      \n   l   a   s
0000140   164 040 141 162 162 141 171 040 166 141 154 165 145 072 040 163
           t       a   r   r   a   y       v   a   l   u   e   :       s
0000160   040 012
              \n
0000162

Как видите, в четвертой строке между пробелами присутствует нулевой байт.

Также обратите внимание, что в программе есть ошибка: %d может не подходить для аргумента типа size_t.Формат C99 %zu, но для переносимости на системы с плохой поддержкой времени выполнения C99 я бы порекомендовал:

printf("Size of array is: %lu\n", (unsigned long)sizeof(strArray));
0 голосов
/ 29 января 2019

Это потому, что в C-строке (массиве символов) последняя позиция является нулевым завершением: '\ 0' используется для завершения C-строки.Таким образом, вы не получите результат, если попытаетесь распечатать последний индекс.Последний элемент фактической строки, таким образом, имеет размер массива - 2, как вы можете видеть из своего вывода.

0 голосов
/ 29 января 2019

Когда вы инициализируете массив char [] строковым литералом, заключенным в двойные кавычки, вы не видите, что нулевой терминатор неявно добавляется в конец строки.Вот почему массив имеет длину 29, хотя ваш строковый литерал содержит только 28 печатаемых символов.

0 голосов
/ 29 января 2019

Когда вы инициализируете массив char строковой константой без указания размера массива, размер массива - это количество символов в строковой константе, плюс 1 для завершающего нулевого байта .

Так что strArray[lastElem-1] имеет значение 0, и печать этого значения в виде символа обычно ничего не печатает.

Если вы должны использовать strlen вместо sizeof, выполучит 28 и strArray[lastElem-1] будет 's'.

0 голосов
/ 29 января 2019

lastElem-1 зарезервирован для '\ 0', который является нулевым терминатором.

Нулевой терминатор ничего не печатает, так как он является часовым для обозначения конца строки, так как если нет нулевого терминатора, простоучитывая некоторый массив символов, неясно, где заканчивается строка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...