2012-03-30 2 views
37
#include "stdio.h" 
#include "string.h" 

main() 
{ 

    char string[] = "october"; // october is 7 letters 

    strcpy(string, "september"); // september is 9 letters 

    printf("the size of %s is %d and the length is %d\n\n", string, sizeof(string), strlen(string)); 

    return 0; 
} 

Выход:Sizeof против STRLEN

размер сентября составляет 8, а длина 9

Есть ли что-то не так с моим синтаксисом или что?

+10

Вы пишете конец конца строки 'string'. Это неопределенное поведение. 'string' может содержать только 8 символов (7 для« октябрь »и 1 для нулевого терминатора). Когда вы вызываете 'strcpy', вы пишете ему 10 символов (9 для« september »и 1 для нулевого терминатора), что означает, что вы прошли мимо конца массива и перезаписываете смежную память. – Marlon

+11

Обратите внимание, что 'sizeof' вычисляется при * компиляции * времени, где в качестве' strlen' используется время выполнения. – Naveen

+5

@Naveen: Имейте в виду, что это не обязательно так, когда задействованы VLA. – caf

ответ

1

Ваш целевой массив равен 8 байтам (длина «октябрь» плюс \ 0), и вы хотите разместить 9 символов в этом массиве.

man strcpy говорит: Если строка назначения strcpy() недостаточно велика, все может произойти.

Пожалуйста, скажите мне, что вы действительно хотите сделать, потому что это плохо пахнет длинный путь

+0

Это тестовая программа для понимания работы sizeof() – beparas

33

sizeof и strlen() делать разные вещи. В этом случае, ваша декларация

char string[] = "october"; 

такая же, как

char string[8] = "october"; 

поэтому компилятор может сказать, что размер string является 8. Он делает это во время компиляции.

Однако strlen() подсчитывает количество символов в строке во время выполнения. Итак, после того, как вы позвоните strcpy(), string теперь содержит «сентябрь». strlen() подсчитывает символы и находит 9 из них. Обратите внимание, что вы не выделили достаточно места для string, чтобы провести «сентябрь». Это неопределенное поведение.

3

Выхода правильно, потому что

первого размер Строка оператора был выделен компилятором, который 7 + 1 (октябрь составляет 7 байт & 1 байт для нулевого терминатора во время компиляции)

Второго утверждения: вы копирование сентябрь (строка от 9 до 8 байтов);

там для вас есть размер сентября в 8 байт (по-прежнему strlen() не будет работать в сентябре он не имеет нулевой символ)

+1

Строковый литерал '' сентябрь '' неявно содержит нулевой символ, поэтому 'strlen()' будет работать, если программа не разбилась уже (из-за записи мимо конца массива 'string') –

-1

Вы должны устранить buffer overflow проблемы в этом примере. Один из способов сделать это - использовать strncpy:

memset(string, 0, sizeof(string)); 
strncpy(string, "september", sizeof(string)-1); 
+1

Нет, нет, нет. 'strncpy()', несмотря на его имя, является неправильным инструментом для чего-либо с ** строками **. В приведенном выше примере результирующая «строка» не будет * строкой *, потому что ни один из ее 8 элементов не будет содержать нулевой терминатор. – pmg

+0

Почему неправильный инструмент? Я исправил проблему завершения строки. –

+0

Это неправильный инструмент для строк именно потому, что он не учитывает нулевой терминатор, который существует в каждой строке по определению ('strncpy()' design делает его полезным только для ... errr ... * un-terminated строки *). Убедитесь, что у вас есть место и используйте 'strcpy()' (или, если вы можете использовать BSD-isms, используйте 'strlcpy()'). – pmg