programing

strcmp 빈 문자열

lovejava 2023. 10. 6. 20:46

strcmp 빈 문자열

코드를 검토하던 중에 누군가가 하는 것을 보았습니다.

if (0 == strcmp(foo,""))

저는 그게 더 빠를 것 같아서 궁금합니다.

if (foo[0] == '\0')

이것이 맞습니까 아니면 둘을 동일하게 만들 수 있을 정도로 strcmmp가 최적화되어 있습니까?

(비록 차이가 있다고 해도 적을 거라는 것을 알고 있지만, 제 방법을 사용해서 최소한 몇 가지 지시사항은 절약할 수 있다고 생각합니다.)

이 맞아요. 에 전화한 이후로.strcmp()스택 관리와 메모리 점프를 실제 strcmp 명령에 추가합니다. 문자열의 첫 번째 바이트만 확인해도 몇 가지 명령을 얻을 수 있습니다.

궁금한 점은 strcmp () 코드를 확인하십시오. http://sourceware.org/git/ ?p=glibc.git;a=blob;f=string/strcmp.c;h= bd53c05c6e21130b091bd75c3fc93872d71fe4b;hb=HEAD

가 (했습니다)로 줄 .#ifdef 불분명한d.__GNUSOMETHING좀 요!)

strcmp ()는 함수 호출이므로 함수 호출 오버헤드가 있습니다.foo[0]는 배열에 직접 접근하기 때문에 확실히 더 빠릅니다.

이 경우 strcmp를 사용해도 아무런 이점이 없다고 봅니다.컴파일러는 최적화할 수 있을 정도로 영리하지만 '\0' 바이트를 직접 확인하는 것보다 빠르지는 않을 것입니다.이것의 시행자는 이것이 더 읽기 쉽다고 생각해서 이 구조물을 선택했을 수도 있지만, 나는 이 경우에 이것이 취향의 문제라고 생각합니다.빈 문자열을 확인할 때 가장 자주 사용하는 관용구이기 때문에 수표를 조금 다르게 쓰겠습니다.

if( !*str )

그리고.

if( *str )

비어 있지 않은 문자열을 확인합니다.

gcc stdlib strcmp(http://sourceware.org/git/ ?p=glibc.git;a=blob;f=string/strcmp.c;h=bd53c05c6e21130b091bd75c33872d71fe4b;hb=HEAD)의 링크를 제공하기 위한 +1 to Gui13!

strcmp가 직접 비교[1]보다 결코 빠를 수 없다는 것은 맞지만, 문제는 컴파일러가 최적화할 것인가 하는 것입니다.저는 그것을 측정해 보려고 겁이 났지만, 그것이 얼마나 쉬운지에 기분 좋게 놀랐습니다.내 샘플 코드는 (헤더 생략):

bool isEmpty(char * str) {
   return 0==std::strcmp(str,"");
}
bool isEmpty2(char * str) {
   return str[0]==0;
}

는 그것을 , 에는.gcc -S -o- emptystrcmptest.cch와 함께gcc -S -O2 -o- emptystrcmptest.cc 최적화되지 않은 은 분명히 , 된 버전은 두 이 동일한 한다는 것을 하게 보여주었습니다 놀랍게도, 비록 어셈블리를 잘 읽지는 못하지만 최적화되지 않은 버전은 분명히 차이를 보였고, 최적화된 버전은 두 기능이 동일한 어셈블리를 만들어내는 것을 명확하게 보여주었습니다.

따라서 일반적으로 이러한 최적화 수준에 대해 걱정할 필요가 없습니다.

임베디드 시스템용 컴파일러를 사용하고 있지만 이러한 단순한 최적화를 처리하지 못하는 경우(또는 표준 라이브러리가 전혀 없는 경우)에는 손으로 코딩된 특수 케이스 버전을 사용합니다.

정상적으로 코딩하는 경우, 보다 판독 가능한 버전(상황에 따라 strcmp 또는 strlen 또는 [0]==0일 수 있는 imho)을 사용합니다.

만약 당신이 매우 효율적인 코드를 쓰고 있다면, 당신이 초당 수천 번 혹은 수백만 번 호출되기를 기대한다면, (a) 실제로 더 효율적인 테스트이고 (b) 만약 읽을 수 있는 버전이 실제로 너무 느리다면, 더 나은 어셈블리로 컴파일될 수 있는 부호를 써보세요.

와 함께gcc -S -o- emptystrcmptest.cc:

            .file   "emptystrcmptest.cc"
            .section .rdata,"dr"
    LC0:
            .ascii "\0"
            .text
            .align 2
    .globl __Z7isEmptyPc
            .def    __Z7isEmptyPc;  .scl    2;      .type   32;     .endef
    __Z7isEmptyPc:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $24, %esp
            movl    $LC0, 4(%esp)
            movl    8(%ebp), %eax
            movl    %eax, (%esp)
            call    _strcmp
            movl    %eax, -4(%ebp)
            cmpl    $0, -4(%ebp)
            sete    %al
            movzbl  %al, %eax
            movl    %eax, -4(%ebp)
            movl    -4(%ebp), %eax
            leave
            ret
            .align 2
    .globl __Z8isEmpty2Pc
            .def    __Z8isEmpty2Pc; .scl    2;      .type   32;     .endef
    __Z8isEmpty2Pc:
            pushl   %ebp
            movl    %esp, %ebp
            movl    8(%ebp), %eax
            cmpb    $0, (%eax)
            sete    %al
            movzbl  %al, %eax
            popl    %ebp
            ret
    emptystrcmptest.cc:10:2: warning: no newline at end of file
            .def    _strcmp;        .scl    2;      .type   32;     .endef

와 함께gcc -S -O2 -o- emptystrcmptest.cc:

        .file   "emptystrcmptest.cc"
emptystrcmptest.cc:10:2: warning: no newline at end of file
        .text
        .align 2
        .p2align 4,,15
.globl __Z7isEmptyPc
        .def    __Z7isEmptyPc;  .scl    2;      .type   32;     .endef
__Z7isEmptyPc:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        cmpb    $0, (%eax)
        sete    %al
        movzbl  %al, %eax
        ret
        .align 2
        .p2align 4,,15
.globl __Z8isEmpty2Pc
        .def    __Z8isEmpty2Pc; .scl    2;      .type   32;     .endef
__Z8isEmpty2Pc:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        cmpb    $0, (%eax)
        sete    %al
        movzbl  %al, %eax
        ret

[1] 0에 대한 직접 테스트보다 복잡한 경우에는 라이브러리와 컴파일러 코드 a가 수작업 코드보다 더 낫습니다.

좋은 최적화 컴파일러는 함수 호출을 최적화한 다음 인라인 함수에서 루프를 제거할 수 있습니다.동일한 속도일 가능성이 있지만 방법이 느릴 수는 없습니다.

배열에 대한 액세스는 실행 시간에서 순서 1이므로 함수보다 빠릅니다.

이것은 최대한 마이크로 최적화된 것이지만, foo를 인덱싱하기 전에 null 체크를 추가했다면(절대 null이 아닐 것이라는 것을 모르는 한) 기능 호출의 오버헤드를 기술적으로 절약할 수 있을 것입니다.

이는 분명 더 빨라질 것이며, 앞으로 나아갈 계획이라면 인라인 기능이나 매크로에 자신만의 코드를 넣을 가치가 있을 것입니다.

int isEmpty(const char *string)
{
    return ! *string;
}

int isNotEmpty(const char *string)
{
    return *string;
}

int isNullOrEmpty(const char *string)
{
    return string == NULL || ! *string;
}

int isNotNullOrEmpty(const char *string)
{
    return string != NULL && *string;
}

컴파일러가 당신을 위해 그것을 최적화 할 수 있게 해주세요.개의치 않고,strcmp최종적으로 확인할 필요가 있습니다.'\0'최소한 당신은 항상 그것과 동등합니다.(솔직히, 저는 컴파일러가 위의 내부 공유를 최적화하도록 할 것입니다. 예를 들어,isEmpty아마도 그냥 뒤집힐 겁니다.isNotEmpty)

언급URL : https://stackoverflow.com/questions/6203102/strcmp-for-empty-string