programing

"strlen(s1) - strlen(s2)"은 0보다 작으면 안 됩니다.

newsource 2022. 8. 19. 20:53

"strlen(s1) - strlen(s2)"은 0보다 작으면 안 됩니다.

저는 현재 문자열 길이를 자주 비교해야 하는 C 프로그램을 작성하고 있기 때문에 다음과 같은 도우미 기능을 작성했습니다.

int strlonger(char *s1, char *s2) {
    return strlen(s1) - strlen(s2) > 0;
}

는 '참'이 '참'이 돌아온다는 되었습니다.s1s2누가 이 이상한 행동에 대해 설명해 줄 수 있나요?

서명된 수량과 서명되지 않은 수량을 모두 포함하는 식을 처리할 때 C에서 발생하는 특이한 동작입니다.

한쪽 오퍼랜드가 서명되고 다른 한쪽 오퍼랜드가 서명되지 않은 조작이 실행되면 C는 암묵적으로 서명된 인수를 부호 없는 인수(unsigned)로 변환하고 숫자가 음이 아닌 것으로 가정하여 조작을 수행합니다.은 종종 이지 않은 .< ★★★★★★★★★★★★★★★★★」>.

기능에 는, 「도움말」이므로, 「도움말」이 되는 것에 .strlen type은 type을 합니다.size_t(부호 없는 수량), 차이 및 비교는 모두 부호 없는 산술을 사용하여 계산됩니다.s1s2, 「」strlen(s1) - strlen(s2)큰 가 없는 큰 숫자입니다.★★★★★★★★★★★★★★★★★★,0★★★★★★★★★★★★★★★★★★,

return strlen(s1) - strlen(s2) > 0;

1s1s2기능을 수정하려면 대신 다음 코드를 사용하십시오.

return strlen(s1) > strlen(s2);

C의 멋진 세계에 오신 것을 환영합니다! :)


기타 예시

이 질문이 최근 많은 관심을 받고 있기 때문에, 제가 확실히 이해시키고 있는지 확인하기 위해 몇 가지 간단한 예를 들어 보겠습니다.저는 우리가 2의 보완 표현을 사용하여 32비트 기계로 작업하고 있다고 가정합니다.

C에서 부호 없는/서명 있는 변수를 사용할 때 이해해야 할 중요한 개념은 단일 식에 부호 없는 수량과 부호 있는 수량이 혼합되어 있는 경우 부호 없는 값은 암묵적으로 부호 없는 값으로 캐스팅된다는 것입니다.

예 1:

다음 식을 고려합니다.

-1 < 0U

두 번째 피연산자는 부호가 없기 때문에 첫 번째 피연산자는 암묵적으로 부호가 없는 피연산자로 캐스팅됩니다.따라서 식은 비교와 동일합니다.

4294967295U < 0U

물론 거짓이죠이것은 아마 당신이 예상한 행동이 아닐 겁니다.

예 2:

합니다.a는 파라미터로 length:

int sum_array_elements(int a[], unsigned length) {
    int i;
    int result = 0;

    for (i = 0; i <= length-1; i++) 
        result += a[i];

    return result;
}

이 기능은 서명된 것부터 서명되지 않은 것까지 암묵적인 캐스팅으로 인해 얼마나 쉽게 버그가 발생할 수 있는지를 보여주기 위해 고안되었습니다. 변수 스러운 것 .length부호 없이, 결국 음의 길이를 사용하려는 사람이 어디 있겠는가? 기준 ' ' 'i <= length-1꽤 직관적인 것 같아요. 인수와 시 " " "가 됩니다.length에 equal 0이 두 가지를 조합하면 예기치 않은 결과가 됩니다.

'''부터length없이 됩니다.0-1는 부호 없는 산술을 사용하여 수행됩니다.이것은 모듈러 덧셈과 동일합니다.결과는 UMax 입니다.<=또한 부호 없는 비교를 사용하여 비교가 수행되며, 모든 숫자가 UMax보다 작거나 같기 때문에 비교는 항상 유지됩니다.따라서 코드는 어레이의 잘못된 요소에 액세스하려고 합니다.a

는, 를 선언하는 할 수 있습니다.length가 되다int'시험'의for를 틀다i < length.

결론:서명 없이 사용해야 하는 경우

여기서 너무 논란이 되는 것은 말하고 싶지 않지만, 여기 C로 프로그램을 작성할 때 자주 지키는 몇 가지 규칙이 있습니다.

  • 숫자가 음수가 아니라고 해서 사용하지 마세요.실수하기 쉽고, 이러한 실수는 때때로 놀라울 정도로 미묘합니다(예 #2 참조).

  • 하다모듈식 연산을 수행할 때 사용합니다.

  • 비트를 사용하여 세트를 나타낼사용하십시오.이것은 종종 부호 확장 없이 논리적인 오른쪽 이동을 수행할 수 있기 때문에 편리합니다.

물론, 이러한 「규칙」에 반하는 상황이 있을 수 있습니다.그러나 대부분의 경우 이러한 제안을 따르면 코드 조작이 쉬워지고 오류 발생률이 낮아집니다.

strlen를 반환하다size_t은 ,입니다.typedef잠 an an unsigneddiscloss.discloss.

그렇게,

(unsigned) 4 - (unsigned) 7 == (unsigned) - 3

★★★★★unsigned이 크다, , 같다, 입니다.0 해서 strlen로로 합니다.long int.

Alex Lockwood의 답변은 최적의 솔루션(구체적, 명확한 의미론 등)입니다.

형식으로 하는 것이 가 있을 수 .size_tptrdiff_t

return ptrdiff_t(strlen(s1)) - ptrdiff_t(strlen(s2)) > 0;

보면 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, size_t이 " "에 들어맞다ptrdiff_t(1번으로 하다)

언급URL : https://stackoverflow.com/questions/10474769/strlens1-strlens2-is-never-less-than-zero