programing

문자 뺄셈을 이용한 cstrcmp 구현

codeshow 2023. 10. 24. 21:39
반응형

문자 뺄셈을 이용한 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_8world (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_t127을 초과하는 값은 오버플로우로 인해 부호가 변경되므로 이를 방지할 수 있지만 출력은 다음과 같습니다.int16_t만약 255 - 0의 결과를 얻었다면 이는 잘린 반환입니다.

언급URL : https://stackoverflow.com/questions/34859163/c-strcmp-implementation-using-subtraction-of-characters

반응형