문자 뺄셈을 이용한 cstrcmp 구현
저는 이러한 구현을 보았습니다.strcmp
조금 전에, 그리고 저는 순수한 교육적인 목적을 위해 질문이 있습니다.입력을 16비트 정수로 변환하고 연산을 한 다음 다시 8비트로 변환해야 하는 이유는 무엇입니까?뺄셈을 8비트로 하는 것이 무슨 문제가 있습니까?
int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
while ( *s1 && (*s1 == *s2) )
{
s1++;
s2++;
}
return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
}
참고: 코드는 16비트를 가정합니다.int
유형.
편집: C가 다음으로 변환을 한다고 언급했습니다.int
(suppose 32비트) 기본값입니다.코드에 명시적으로 16비트로 캐스팅하라고 명시되어 있는 경우에도 그러합니까?int
?
strcmp(a,b) 함수가 반환될 것으로 예상됩니다.
<0
한다면string a < string b
>0
한다면string a > string b
0
한다면string a == string b
테스트는 실제로 첫 번째 문자가 동일한 위치에 있는 두 개의 문자열에서 서로 다른 경우에 수행됩니다( 문자열 터미네이터 0도 작동).
여기서 기능은 2개가 필요합니다.uint8_t
(무부호 문자), 개발자는 아마도 두 개의 무부호 문자를 비교하는 것에 대해 걱정하고 있었을 것입니다.0
그리고.255
, 따라서 음의 값은 절대로 반환되지 않습니다.예를 들어.118 - 236
돌아올 것입니다-118
, 하지만 8비트에서는 돌아올 것입니다.138
.
그래서 프로그래머는 캐스팅을 하기로 결정했습니다.int_16
, 부호가 있는 정수(16비트).
이는 효과가 있었고 정확한 음/양의 값이 주어졌을 수도 있습니다(기능이 다시 돌아온다면).int_16
대신에int_8
).
(*edit : 아래 @zwol 님의 코멘트, 정수 프로모션은 부득이하게 진행되므로,int16_t
캐스팅은 필요 없음)
하지만 결승전은int_8
캐스팅이 논리를 깨뜨립니다.반환된 값이 다음 값일 수 있습니다.-255
로.255
, 이 값들 중 일부는 캐스트 후에 그들의 부호가 역전되는 것을 볼 것입니다.int_8
.
예를 들면 하기.255 - 0
긍정적인 것을 주다255
(16비트의 경우 모두 8비트에서 1로, MSB에서 0으로 낮춥니다.int_8
world (8비트로 서명) 이건 음성이고,-1
, 마지막 로우 8비트만 바이너리로 설정할 수 있기 때문에11111111
, 또는 십진법-1
.
Definitely not a good programming example.
That 작업기능 from Apple is better
for ( ; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
(Linux는 어셈블리 코드에서 실행합니다...)
실제로 결과의 범위가 -255~255이고 8비트에 맞지 않는 것은 명백한 이유로 최소 16비트 ¹에서 차이를 수행해야 합니다.하지만 어쨌든 암묵적인 정수 홍보로 인해 발생할 것이라는 점은 sfstewman이 옳습니다.
범위가 여전히 8비트에 맞지 않기 때문에 오버플로가 발생할 수 있기 때문에 8비트에 대한 최종 캐스트는 올바르지 않습니다.그리고 어쨌든, 정말로 평범하게 돌아올 것입니다.int
.
¹ 9개면 충분하지만 비트는 보통 8개 묶음으로 나옵니다.
입력 데이터는 부호가 없는 8비트이므로 잘라내기 및 오버플로/언더플로의 영향을 방지하려면 적어도 9비트 부호로 변환해야 하므로 int16이 사용됩니다.
return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
이는 다음 두 가지 옵션 중 하나를 의미할 수 있습니다.
프로그래머가 C에서 암묵적 유형의 프로모션이 어떻게 작동하는지에 대해 혼란스러워했습니다.두 피연산자 모두 암묵적으로 다음으로 변환됩니다.
int
…에 캐스팅 되더라도int16_t
. 그래서 만약에int
예를 들어 32비트, 코드는 넌센스입니다.아니면 그렇지 않다면int
와 동치입니다.int16_t
특정 시스템의 경우 변환이 전혀 이루어지지 않습니다.또는 프로그래머는 유형 프로모션이 어떻게 작동하는지 잘 알고 있으며 MISRA-C와 같은 암묵적 유형 프로모션을 금지하는 표준에 확인해야 하는 코드를 작성하고 있습니다.그 경우엔, 그리고 그 경우엔
int
주어진 시스템에서 16비트인 코드는 완벽하게 맞아 떨어집니다. 컴파일러/정적 분석기의 경고를 피하기 위해 명시적인 형식 프로모션을 강제로 수행합니다.
두 번째 옵션이 가장 가능성이 높고, 이 코드는 소형 마이크로컨트롤러 시스템을 위한 것이라고 추측합니다.
다음과 같은 경우 두 숫자 사이의 차이를 유발하는 특정 값이 있습니다.int16_t
물이 넘쳐서 없었던 것 같습니다.int8_t
당신의 범위는 -128에서 127입니다.uint8_t
당신의 범위는 0에서 255까지 입니다.int16_t
당신의 범위는 -32,768에서 32,767입니다.
케이스를 안으로int8_t
로부터uint8_t
127을 초과하는 값은 오버플로우로 인해 부호가 변경되므로 이를 방지할 수 있지만 출력은 다음과 같습니다.int16_t
만약 255 - 0의 결과를 얻었다면 이는 잘린 반환입니다.
언급URL : https://stackoverflow.com/questions/34859163/c-strcmp-implementation-using-subtraction-of-characters
'programing' 카테고리의 다른 글
ngIf - 확인 후 식이 변경되었습니다. (0) | 2023.10.24 |
---|---|
void* 대신 intptr_t를 사용? (0) | 2023.10.24 |
jQuery로 텍스트 내용별 옵션 선택 (0) | 2023.10.24 |
AND() 함수를 이용한 조건부 포맷 (0) | 2023.10.24 |
MySQL SELECT 쿼리에서 IF 문 사용 (0) | 2023.10.24 |