"strlen(s1) - strlen(s2)"은 0보다 작으면 안 됩니다.
저는 현재 문자열 길이를 자주 비교해야 하는 C 프로그램을 작성하고 있기 때문에 다음과 같은 도우미 기능을 작성했습니다.
int strlonger(char *s1, char *s2) {
return strlen(s1) - strlen(s2) > 0;
}
는 '참'이 '참'이 돌아온다는 되었습니다.s1
가 s2
누가 이 이상한 행동에 대해 설명해 줄 수 있나요?
서명된 수량과 서명되지 않은 수량을 모두 포함하는 식을 처리할 때 C에서 발생하는 특이한 동작입니다.
한쪽 오퍼랜드가 서명되고 다른 한쪽 오퍼랜드가 서명되지 않은 조작이 실행되면 C는 암묵적으로 서명된 인수를 부호 없는 인수(unsigned)로 변환하고 숫자가 음이 아닌 것으로 가정하여 조작을 수행합니다.은 종종 이지 않은 .<
★★★★★★★★★★★★★★★★★」>
.
기능에 는, 「도움말」이므로, 「도움말」이 되는 것에 .strlen
type은 type을 합니다.size_t
(부호 없는 수량), 차이 및 비교는 모두 부호 없는 산술을 사용하여 계산됩니다.s1
s2
, 「」strlen(s1) - strlen(s2)
큰 가 없는 큰 숫자입니다.★★★★★★★★★★★★★★★★★★,0
★★★★★★★★★★★★★★★★★★,
return strlen(s1) - strlen(s2) > 0;
1
라 s1
s2
기능을 수정하려면 대신 다음 코드를 사용하십시오.
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 unsigned
discloss.discloss.
그렇게,
(unsigned) 4 - (unsigned) 7 == (unsigned) - 3
★★★★★unsigned
이 크다, , 같다, 입니다.0
해서 strlen
로로 합니다.long int
.
Alex Lockwood의 답변은 최적의 솔루션(구체적, 명확한 의미론 등)입니다.
형식으로 하는 것이 가 있을 수 .size_t
ptrdiff_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
'programing' 카테고리의 다른 글
부트스트랩 Vue 방지/취소 이벤트 (0) | 2022.08.19 |
---|---|
Vue-Router는 라우터 링크가 아닌 일반 앵커로부터의 클릭을 처리할 수 있습니까? (0) | 2022.08.19 |
Maven's pom.xml의 plugin Management란 무엇입니까? (0) | 2022.08.19 |
C/C++ 어플리케이션용 오픈소스 PDF 라이브러리 (0) | 2022.08.19 |
Vue 2 및 Vuex에서 전달된 프로펠러를 변수로 사용하여 오브젝트 속성에 동적으로 액세스하면 오류가 반환된다. (0) | 2022.08.19 |