문자열의 문자 수를 계산하는 함수입니다.
int str_len(const char* s) {
int i = 0;
while(*(s++)) {
i++;
}
return i;
}
이것이 올바른 길이를 반환하는 이유는 무엇입니까?
간단한 String 으로이 함수를 호출한다고 가정 해 봅시다 "a". 그런 다음 swhile 루프에서 증가하므로 s및 의 값 i은 모두 0입니다.
답변
의 값은 증분 이전 s++의 원래 값으로 s, 증분은 다음 시퀀스 포인트 전의 지정되지 않은 시간에 발생합니다.
따라서 *s++및*(s++) 동일 : 그들은 모두의 원래 값을 역 참조 s. 또 다른 동등한 표현은 *(0, s++)마음이 희미하지 않은 것이 아니라 다음과 같습니다.0[s++]
그러나 함수는 type size_t을 사용해야합니다 .i 과 반환 유형 합니다.
size_t str_len(const char *s) {
size_t i = 0;
while (*s++) {
i++;
}
/* s points after the null terminator */
return i;
}
다음은 루프 당 단일 증분이있는 잠재적으로 더 효율적인 버전입니다.
size_t str_len(const char *s) {
const char *s0 = s;
while (*s++) {
/* nothing */
}
return s - 1 - s0;
}
두 번째 단락의 이상한 표현에 대해 궁금해하는 사람들을 위해 :
-
0, s++,왼쪽 부분을 평가 한 다음 오른쪽 부분을 평가 하는 쉼표 연산자의 인스턴스입니다 . 그 후(0, s++)와 같습니다(s++). -
0[s++]동등(s++)[0]하고*(0 + s++)또는*(s++ + 0)같은 단순화 된*(s++). 표현식에서 포인터와 색인 표현식을 전치하는[]것은 흔하지 않거나 특히 유용하지는 않지만 C 표준을 준수합니다.
답변
간단한 문자열 “a”로이 함수를 호출한다고 가정 해 봅시다. 그런 다음 while 루프에서 s가 증가하므로 s의 값은 0이고 i도 0입니다.
이 예 s에서 'a'in을 가리 킵니다 "a". 그런 다음 증분되고 i증분됩니다. 이제 s널 종료자를 가리키고 iis 1입니다. 따라서 다음에 루프를 통과하면 *(s++)is '\0'( 0)이므로 루프가 종료되고 현재의 값 i( 1)이 반환됩니다.
일반적으로 루프는 문자열의 각 문자에 대해 한 번 실행 된 다음 널 종료 자에서 중지되므로 문자 수를 계산합니다.
답변
완벽하게 이해됩니다.
int str_len(const char* s) {
int i = 0;
while(*(s++)) { //<-- increments the pointer to char till the end of the string
//till it finds '\0', that is, if s = "a" then s is 'a'
// followed by '\0' so it increments one time
i++; //counts the number of times the pointer moves forward
}
return i;
}
“하지만
s대괄호 안에 있습니다. 그것이 내가 먼저 증가 할 것이라고 생각한 이유입니다.”
그렇기 때문에 포인터가 문자가 아닌 증분되는 이유입니다.이 경우 포인터가 아니라 (*s)++문자가 증분됩니다. 역 참조는 이제 포인터 자체가 아니라 포인터가 참조하는 값으로 작업하고 있음을 의미합니다.
두 연산자의 우선 순위는 같지만 오른쪽에서 왼쪽으로의 연관성이 있으므로 *s++대괄호없이 간단히 포인터를 사용할 수도 있습니다 .
답변
사후 증분 연산자는 피연산자의 값을 1 씩 증가 시키지만 표현식의 값은 증분 연산 이전의 피연산자의 원래 값입니다.
전달 된 인수가 str_len()입니다 "a". 에서 str_len(), 포인터는 s문자열의 첫 번째 문자를 가리키고 있습니다 "a". 에서 while루프 :
while(*(s++)) {
.....
.....
가 있지만 s증가하지만 될 값 s의 표현은 첫 번째 문자에 포인터가 증가하기 전에 가리키는 문자에 대한 포인터 일 것이다 'a'. 포인터 s가 역 참조 되면 character가 제공됩니다 'a'. 다음 반복에서 s포인터는 널 문자 인 다음 문자를 가리 킵니다 \0. s역 참조 되면 0루프가 종료됩니다. 그 참고 s이제 문자열의 NULL 문자 과거 하나 개의 요소를 가리키는 것입니다 "a".
답변
