2010-04-23 4 views
5

난 정말 다른 간단한 C 질문으로 모두 당신을 귀찮게했습니다.빠른 strlen 질문

다음 코드를 사용 :

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

이 질문에. 그들은 왜 다른가? 그리고 왜 6인가? 고마워.

편집 : 죄송합니다. 문제를 해결할 수 있을지 알고 있습니다. 무슨 일인지 이해하고 싶었습니다. strlen은 \ 0을 찾을 때까지 계속 전달할 것입니다. 또한 내가 get_len 함수 대신에 main 함수에서 strlen했을 때 둘 다 4였습니다. 그냥 우연의 일치입니까?

+0

예, 그냥 우연이었습니다. – AnT

+0

't', 'e', ​​'s', 't'시퀀스에 대한 편리한 문법 인 반면에, "test" , 0', 사실 특별한 경우로 char 배열을'char y [4] = "test";로 초기화 할 수 있습니다.이 경우 마지막 0은 생략 될 것입니다 ('y'). –

답변

13

y은 null로 끝나지 않습니다. 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; 
} 
+0

그래서 strlen은 포인터를 전달할 때까지 어디서나 \ 0 찾을 수 있습니까? – LearningC

+1

@LearningC : 맞아. 그것은 포인터를 증가시키고 거기에있는 것을 보아줍니다. 0을 찾으면 멈추고보고있는 문자 수 (0 제외)를 반환합니다. –

+4

@LearningC : 예. 아니면 segfault가 충돌 할 때까지. 또는 하드 드라이브를 포맷 할 때까지. 입력이 0으로 종료되지 않은 경우 동작은 * 정의되지 않음 *입니다. * 아무거나 * 일어날 수있다. – AnT

2

y를 null 종료해야합니다.

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까지 바이트 수를 계산합니다. 너의 기억에 나중에 2 바이트의 NULL이 있었을 뿐이다.

+0

그래서 strlen은 포인터를 전달할 때까지 어디서나 \ 0 찾을 수 있습니다? – LearningC

+0

두 가지 문제가 있습니다. 첫째, NULL은 null 문자가 아니라 널 포인터로 사용됩니다. 둘째, 여전히 'char y [4]'를 얻었으므로 여분의 초기화 도구가 있습니다. "테스트"문자열을 사용하려면 다섯 가지 순위가 필요합니다. –

+0

@LearningC : 한 마디로, 그렇습니다. 그것은 좋은 설명입니다. –

4

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

적당한 제로 말단 S 아니다 tyring. 이없는 문자 배열은이며 종료 문자는 '\0'입니다. strlen()은 단순히 0에 도달 할 때까지 문자를 카운트합니다. y을 사용하면 우연히 0 바이트를 찾을 때까지 단순히 배열의 끝을 카운트합니다.
이렇게하면 정의되지 않은 동작이 호출됩니다. 이 코드는 하드 드라이브의 형식을 지정할 수도 있습니다.

당신은 문자 배열 초기화를 위해 특수 구문을 사용하여이 문제를 피할 수 있습니다 : 그것은 자동으로 '\0'를 추가하기 때문에

char y[] = "test"; 

이, 다섯 문자로 y를 초기화합니다.
배열의 크기를 지정하지 않은 채로 두었습니다. 컴파일러는 이것을 알아 내고 문자열의 길이를 변경하면 자동으로 다시 수치를 표시합니다.

은 BTW, 여기에 간단한 strlen() 구현의 :

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

현대 구현 가능성이 개별 바이트를 가져 오기 또는 CPU의 내장 함수를 사용하지 않습니다, 그러나 이것은 기본적인 알고리즘이다.strlen()의 계약

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

파트가 널 (null) 문자열을 종료에이 포인터가 제공 될 것입니다 :

+0

와우, 광산을 추가하기 전에 당신의'strlen()'을 보지 못했습니다. 그들은 동일합니다! 위대한 마음 ... 8v) –

+0

문자열 함수를위한 GNU libc 소스는 놀랍도록 복잡하고, 놀라 울 정도로 복잡합니다. –

+0

@Fred : C 라이브러리의 가장 기본적인 알고리즘 중 하나이며 K & R의 대표적인 예입니다. 우리 중 대부분이 자신의 기억에 각인되어 있는지 궁금하지 않습니다. – sbi

3

다음은 문자의 널 (null) 종료 배열이 아닌. strlen(y)에서 발생하지 않으므로 정의되지 않은 동작이 발생합니다. 특정 경우에는 6이 반환되지만 프로그램 충돌을 포함하여 어떤 일이 발생할 수 있습니다.

C99의 7.1.1 "용어의 정의"에서

:

문자열 첫 번째 널 문자를 포함 연속에 의해 종료 문자의 순서와입니다.

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

문자열

char *x = "test"; 
+1

'strlen()'의 목적을 위해. 그러나'y'는 다섯 개의'char' 배열이며, 그 내용은 마음대로 수정할 수 있습니다. 'x'는'char'에 대한 포인터이며,이 경우에는 안정 적으로 수정할 수없는 문자열을 가리 킵니다. 반면에 'x'에는 값을 재 할당 할 수 있지만 'y'에는 재 할당 할 수 없습니다. –

+0

@David Thornley 대답은 OP에 따라 잘못 된 것을 설명하기위한 초보자 용으로 만 제공되었습니다. 이제 더 나은 대답이 주어졌습니다. – stacker

+0

IME는이 차이만큼 미묘한 차이점이 있습니다 ('x [0] = 'x';'char x [] = "X";'라고 말했을 때 괜찮습니다.)'char * x = "X";)는 너무 많은 스트레스를받을 수 없습니다. – sbi

3

strlen 작품과 같은 것입니다. 문자열은 \0 문자로 끝나는 문자의 시퀀스 (배열)로 정의됩니다.

x 문자열을 가리 킵니다. 따라서 strlenx을 인수로 사용하면 문제가 없습니다.

y는 문자열이 아닙니다. 이러한 이유로 ystrlen으로 전달하면 정의되지 않은 동작이 발생합니다. 결과는 의미없고 예측할 수 없습니다.

1

실제 C 유형 문자열은 종료 문자가 필요하기 때문에 문자의 수보다 큰 문자입니다.

따라서 char y[4] = {'t','e','s','t'};은 4 자이기 때문에 문자열을 구성하지 않습니다. char y[] = "test"; 또는 char y[5] = "test";은 널 바이트 종결 자로 끝나는 5 문자의 문자 배열을 가지므로 문자열을 형성합니다.

0

다른 사람들도 말했듯이, 0 또는 '\ 0'문자로 끝나는 문자열을 확인해야합니다. 부수적으로, 당신은 이것을 밖으로 검사 할지도 모른다 : http://bstring.sourceforge.net/. 오류가 발생하기 쉽고 O (N)에서 느린 C/C++ strlen과 달리 O (1) 문자열 길이 함수가 있습니다. 여기서 N은 null이 아닌 문자의 수입니다. 나는 strlen을 사용했을 때 마지막으로 기억하지 못합니다. 안전한 & 빠른 기능/수업을 위해 가십시오!