"strlen (s1)-strlen (s2)"는 0보다 작지 않습니다.
현재 문자열 길이를 자주 비교해야하는 C 프로그램을 작성 중이므로 다음 도우미 함수를 작성했습니다.
int strlonger(char *s1, char *s2) {
return strlen(s1) - strlen(s2) > 0;
}
s1길이가보다 짧은 경우에도 함수가 true를 반환하는 것으로 나타났습니다 s2. 누군가이 이상한 행동을 설명해 주시겠습니까?
당신이 본 것은 부호있는 양과 부호없는 양을 모두 포함하는 표현식을 다룰 때 C에서 발생하는 몇 가지 특이한 동작입니다.
한 피연산자가 부호가 있고 다른 피연산자가 부호없는 연산이 수행되면 C는 암시 적으로 부호있는 인수를 부호없는 인수로 변환하고 숫자가 음수가 아니라고 가정하여 연산을 수행합니다. 이 협약은 종종 같은 관계 연산자에 대한 비 직관적 행동에 이르게 <하고 >.
도우미 함수와 관련하여 strlen반환 유형 size_t(부호없는 수량)이므로 차이와 비교는 모두 부호없는 산술을 사용하여 계산됩니다. 경우 s1보다 짧은 s2, 차이가 strlen(s1) - strlen(s2)음수 일 수 있지만, 대신에보다 큰 대형 부호 번호하게한다 0. 그러므로,
return strlen(s1) - strlen(s2) > 0;
보다 짧은 1경우에도 반환 됩니다 . 함수를 수정하려면 대신 다음 코드를 사용하세요.s1s2
return strlen(s1) > strlen(s2);
멋진 C의 세계에 오신 것을 환영합니다! :)
추가 예
이 질문은 최근에 많은 관심을 받았기 때문에 아이디어를 전달할 수 있도록 몇 가지 (간단한) 예를 제공하고 싶습니다. 2의 보수 표현을 사용하는 32 비트 머신으로 작업한다고 가정하겠습니다.
C에서 부호없는 / 부호있는 변수로 작업 할 때 이해해야 할 중요한 개념 은 단일 표현식에 부호없는 수량과 부호있는 수량이 혼합 된 경우 부호있는 값이 암시 적으로 unsigned로 캐스팅된다는 것 입니다.
예 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를 unsigned 로 전달하는 것은 매우 자연스러운 일입니다 . 결국 누가 음수 길이를 사용하고 싶습니까? 중지 기준 i <= length-1도 매우 직관적 인 것 같습니다. 그러나 인수가와 length같은 0경우이 두 가지를 조합하면 예기치 않은 결과가 발생합니다.
매개 변수 length가 unsigned 이기 때문에 계산 0-1은 unsigned 산술을 사용하여 수행되며 이는 모듈러 덧셈과 동일합니다. 결과는 UMax 입니다. <=비교는 비교의 부호를 사용하여 수행하고, 임의의 수보다 작거나 같은 이후된다 UMAX , 비교를 항상 유지한다. 따라서 코드는 array의 유효하지 않은 요소에 액세스하려고 시도합니다 a.
코드는 선언하거나 고정 될 수 length이어야 int하거나의 시험 변경 for될 루프 i < length.
결론 : Unsigned는 언제 사용해야합니까?
여기에 너무 논란이 많은 것을 말하고 싶지는 않지만 C로 프로그램을 작성할 때 자주 고수하는 몇 가지 규칙이 있습니다.
숫자가 음수가 아니기 때문에 사용 하지 마십시오 . 실수하기 쉽고 이러한 실수는 때때로 매우 미묘합니다 (예제 # 2 참조).
DO 모듈러 연산을 수행 할 때 사용한다.
DO는 세트를 나타내는 비트를 사용하는 경우 사용한다. 부호 확장없이 논리적 오른쪽 이동을 수행 할 수 있기 때문에 종종 편리합니다.
물론 이러한 "규칙"에 어긋나는 상황이있을 수 있습니다. 그러나 대부분의 경우 이러한 제안을 따르면 코드 작업이 더 쉬워지고 오류 발생 가능성이 줄어 듭니다.
strlen유형에 대한 a size_t를 반환합니다 .typedefunsigned
그래서,
(unsigned) 4 - (unsigned) 7 == (unsigned) - 3
All unsigned values are greater than or equal to 0. Try converting the variables returned by strlen to long int.
Alex Lockwood's answer is the best solution (compact, clear semantics, etc).
Sometimes it does make sense to explicitly convert to a signed form of size_t: ptrdiff_t, e.g.
return ptrdiff_t(strlen(s1)) - ptrdiff_t(strlen(s2)) > 0;
If you do this, you'll want to be certain that the size_t value fits in a ptrdiff_t (which has one fewer mantissa bits).
참고URL : https://stackoverflow.com/questions/10474769/strlens1-strlens2-is-never-less-than-zero
'Program Club' 카테고리의 다른 글
| jquery 클릭이 ajax 생성 콘텐츠에서 작동하지 않습니다. (0) | 2020.10.15 |
|---|---|
| PHP-FPM 및 Nginx : 502 불량 게이트웨이 (0) | 2020.10.15 |
| 가져 오기 android.support.v7을 확인할 수 없습니다. (0) | 2020.10.15 |
| 기본 관련 프로그램으로 파일을 여는 방법 (0) | 2020.10.14 |
| Java가 지원하지 않는 주요 부 버전 52.0 (0) | 2020.10.14 |