Быстрый вопрос - PullRequest
       44

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

5 голосов
/ 24 апреля 2010

Я пришел побеспокоить вас всех с другим, возможно, очень простым вопросом 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 вопроса.Почему они разные и почему у 6?Спасибо, ребята.

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

Ответы [ 8 ]

13 голосов
/ 24 апреля 2010

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;
}
4 голосов
/ 24 апреля 2010

Это

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;
}

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

3 голосов
/ 24 апреля 2010

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

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

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

3 голосов
/ 24 апреля 2010

Следующее не является массивом символов с нулевым символом в конце:

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

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

Из C.1.1.1 «Определение терминов»:

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

2 голосов
/ 24 апреля 2010

Вам нужно завершить ноль у.

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.

1 голос
/ 24 апреля 2010

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

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

0 голосов
/ 24 апреля 2010

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

0 голосов
/ 24 апреля 2010
char y[5] = {'t','e','s','t','\0'};

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

char *x = "test"; 
...