2016-02-18 3 views
2

Вот мой код:STRLEN поведение функции на одного символа

void func(char c) 
{ 
    char * ptr = &c; 
    size_t len = strlen(ptr); 
    printf("len - %d\n", len); 
} 

len всегда печатается 1.

strlen(..) определяет длину char массива, находя нулевой символ (\0) на конец его. Здесь ptr инициализируется только адресом одного символа (c). c не содержит никаких нулевых символов. Как ptr получить длину?

+2

«У моего кода есть ошибка, почему он делает что-то странное?» Ну, потому что у него есть ошибка. Исправьте ошибку, и тайна исчезнет. –

+0

«Я сделал плохо. Я знаю, что я сделал плохо. В результате произошли плохие вещи. Объяснить, почему'. Имеет downvote :( –

ответ

7

Вы не можете использовать strlen() указатель, который не указывает на массив с нулевым завершением. Он вызывает undefined behavior.

Как только ваша программа попадает в UB, ничего не гарантируется.

FWIW, strlen() возвращает тип size_t, поэтому вы должны использовать спецификатор формата %zu для печати результата.

+1

Спецификатор формата должен быть '% zu'. – haccks

+0

@haccks abosolutely, обновлено. :) –

4

Поведение вашего кода undefined по двум признакам. Он возвращает 1 случайно.

  1. strlen работ, начиная с указанного адреса, и увеличивающиеся этот адрес до \0 достигнута. Это согласуется с тем, как строчная библиотека моделей C моделирует строки. Если вы не владеете всей памятью (как непрерывным блоком) между начальным адресом и \0, тогда ввод strlen будет искажен.

  2. Поведение printf не определено из-за неправильного спецификатора формата. Используйте %zu для size_t.

0

с не содержит нулевых символов. Как ptr получает длину?

Это не так. Кажется, он дает правильный ответ в ваших тестах, потому что ячейка памяти, следующая за адресом c, содержит нулевой байт. Это местоположение не определено, чтобы содержать нуль, и программа не имеет доступа к нему, поэтому вы не можете рассчитывать на то, что такой код продолжает работать.

В языке стандарта C, поведение программы является неопределенным, что означает, что не только является результатом операции непредсказуемой, the entire program is rendered meaningless.

Даже без учета неопределенного поведения, указанное код может перестать работать с малейшим изменением - например, при изменении архитектуры, компилятора или даже флагов компиляции или при добавлении дополнительных функций в микс. Хотя такие фрагменты кода могут быть полезны для изучения того, как материал работает под капотом, они никогда не должны использоваться в производственном коде.

Смежные вопросы