Быстрый strlen вопрос

Я приехал для беспокойства Вас всех другим, вероятно, действительно простой вопрос C.

Использование следующего кода:

int get_len(char *string){

    printf("len: %lu\n", strlen(string));

    return 0;
}

int main(){

    char *x = "test";
    char y[4] = {'t','e','s','t'};

    get_len(x); // len: 4
    get_len(y); // len: 6

    return 0;
}

2 вопроса. Почему они отличаются и почему y 6?Спасибо, ребята.

Править: Извините, я знаю то, что зафиксировало бы его, я отчасти просто хотел понять то, что продолжалось. strlen просто продолжает передавать точку, пока это, оказывается, не находит \0? Также, когда я сделал strlen в основной функции вместо в функции get_len, оба равнялись 4. Это было просто совпадением?

6
задан LearningC 23 April 2010 в 20:54
поделиться

8 ответов

y не заканчивается нулем. strlen () считает символы, пока не встретит нулевой символ. Вашему довелось найти один после 6, но это могло быть любое число. Попробуйте следующее:

char y [] = {'t', 'e', ​​'s', 't', '\ 0'};

Вот что такое реализация strlen () может выглядеть так (в верхней части моей головы - у меня нет под рукой моей книги K&R, но я считаю, что там есть реализация):

size_t strlen(const char* s)
{
    size_t result = 0;
    while (*s++) ++result;
    return result;
}
14
ответ дан 8 December 2019 в 03:52
поделиться

Вам нужно завершить y нулевым символом в конце.

int get_len(char *string){

    printf("len: %lu\n", strlen(string));

    return 0;
}

int main(){

    char *x = "test";
    char y[5] = {'t','e','s','t','\0'};

    get_len(x); // len: 4
    get_len(y); // len: 4

    return 0;
}

strlen () в основном берет указатель, который вы ему даете, и подсчитывает количество байтов до следующего NULL в памяти. Так уж получилось, что двумя байтами позже в вашей памяти был NULL.

2
ответ дан 8 December 2019 в 03:52
поделиться

Фактическая строка C-типа на единицу больше, чем количество ее символов, поскольку ей нужен завершающий нулевой символ.

Следовательно, char y [4] = {'t', 'e', ​​'s', 't'}; не формирует строку, так как это четыре символа. char y [] = "test"; или char y [5] = "test"; будут формировать строку, поскольку они будут иметь массив символов из пяти символов, оканчивающихся на терминатор нулевого байта.

1
ответ дан 8 December 2019 в 03:52
поделиться

Как уже говорили другие, вам просто нужно обязательно закончить строку символом 0 или '\ 0'. В качестве примечания вы можете проверить это: http://bstring.sourceforge.net/ . Он имеет функцию длины строки O (1), в отличие от strlen C / C ++, которая подвержена ошибкам и медленна при O (N), где N - количество ненулевых символов. Я не помню, когда в последний раз использовал strlen и его друзья. Выбирайте безопасные и быстрые функции / классы!

0
ответ дан 8 December 2019 в 03:52
поделиться

Следующее не является массивом символов с завершающим нулем:

 char y[4] = {'t','e','s','t'};

Часть контракта strlen () заключается в том, что ему должен быть предоставлен указатель на строку с завершающим нулем. Поскольку этого не происходит с strlen (y) , вы получаете неопределенное поведение. В вашем конкретном случае вы получите 6 , но может произойти что угодно, включая сбой программы.

Из раздела 7.1.1 C99 «Определение терминов»:

строка - это непрерывная последовательность символов, оканчивающаяся первым нулевым символом и включающая его.

3
ответ дан 8 December 2019 в 03:52
поделиться

strlen работает с строками . Строка определяется как последовательность (массив) символов, оканчивающихся символом \ 0 .

Ваш x указывает на строку. Итак, strlen отлично работает с x в качестве аргумента.

Ваш y не является строкой. По этой причине передача y в strlen приводит к неопределенному поведению. Результат бессмысленный и непредсказуемый.

3
ответ дан 8 December 2019 в 03:52
поделиться
char y[5] = {'t','e','s','t','\0'};

будет таким же, как

char *x = "test"; 
0
ответ дан 8 December 2019 в 03:52
поделиться

Это

char y[4] = {'t','e','s','t'};

не является правильной строкой с завершающим нулем . Это массив из четырех символов, без завершающего '\ 0' . strlen () просто считает символы, пока не достигнет нуля. С y он просто считает до конца массива, пока случайно не найдет нулевой байт.
При этом вы вызываете неопределенное поведение. Код может с таким же успехом отформатировать ваш жесткий диск.

Этого можно избежать, используя специальный синтаксис для инициализации массива символов:

char y[] = "test";

Это инициализирует y с пятью символами, поскольку автоматически добавляет '\ 0 '.
Обратите внимание, что я также не указал размер массива. Компилятор сам это вычисляет и автоматически повторно вычисляет, если я изменяю длину строки.

Кстати, вот простая реализация strlen () :

size_t strlen(const char* p)
{
    size_t result = 0;
    while(*p++) ++result;
    return result;
}

Современные реализации, скорее всего, не будут извлекать отдельные байты или даже использовать встроенные функции ЦП, но это основной алгоритм.

4
ответ дан 8 December 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: