IT이야기

루프 조건에서 사용할 경우 strlen이 여러 번 계산되는가?

cyworld 2022. 5. 7. 09:37
반응형

루프 조건에서 사용할 경우 strlen이 여러 번 계산되는가?

다음 코드가 중복 계산을 유발할 수 있는지, 아니면 컴파일러에 특정한 것인지 잘 모르겠다.

for (int i = 0; i < strlen(ss); ++i)
{
    // blabla
}

strlen()마시다 할 하다.i증가?

strlen()각 반복에 대해 평가될 것이다.이상적인 상황에서는 최적자가 가치가 변하지 않을 것이라고 추론할 수 있을지도 모르지만, 나는 개인적으로 그것에 의존하지 않을 것이다.

뭐 이런 거라도 할 텐데.

for (int i = 0, n = strlen(ss); i < n; ++i)

또는 아마도

for (int i = 0; ss[i]; ++i)

반복하는 동안 문자열이 길이가 변하지 않는 한만약 가능하다면, 당신은 전화를 해야 할 필요가 있다.strlen()매번, 또는 더 복잡한 논리를 통해 처리한다.

네, 루프를 사용할 때마다.그러면 끈의 길이를 계산할 때마다 이렇게 사용하십시오.

char str[30];
for ( int i = 0; str[i] != '\0'; i++)
{
//Something;
}

위 코드에서str[i] 문자열에 이다.i루프가 사이클을 시작할 때마다, 따라서 그것은 더 적은 메모리를 필요로 하고 더 효율적이다.

자세한 내용은 이 링크를 참조하십시오.

루프가 실행될 때마다 아래 코드에서strlen효율성이 떨어지고, 시간이 더 걸리고, 메모리가 더 많이 걸리는 전체 문자열의 길이를 셀 것이다.

char str[];
for ( int i = 0; i < strlen(str); i++)
{
//Something;
}

훌륭한 컴파일러가 매번 계산하지는 않겠지만, 모든 컴파일러가 계산한다고 확신할 수는 없을 겁니다.

게다가 컴파일러는 그 사실을 알아야 한다.strlen(ss)변하지 않는다.이것은 오직 다음과 같은 경우에만 사실이다.ss에서 변경되지 않음for고리를 두르다

예를 들어, 읽기 전용 함수를 사용하는 경우ssfor반복하지만 선언하지는 마십시오.ss-로 평가됨const, 컴파일러는 심지어 알지도 못한다.ss루프에서 변경되지 않고 계산해야 함strlen(ss)매 번 되풀이하여

만약ss형식이다.const char *그리고 당신은 그 사람을 쫓아내지 않을 것이다.const컴파일러가 호출만 할 수 있는 루프 내의 nessstrlen최적화가 켜져 있는 경우 1회.그러나 이것은 확실히 기댈 수 있는 행동이 아니다.

당신은 그 일을 저장해야 한다.strlen변수를 생성하여 루프에 이 변수를 사용하십시오.만약 당신이 어떤 행동을 하느냐에 따라 추가적인 변수를 만들고 싶지 않다면, 당신은 반복하기 위해 루프를 거꾸로 돌리는 것을 피할 수 있을 것이다.

for( auto i = strlen(s); i > 0; --i ) {
  // do whatever
  // remember value of s[strlen(s)] is the terminating NULL character
}

공식적으로 네,strlen()모든 반복이 요구될 것으로 예상된다.

어쨌든 나는 어떤 영리한 컴파일러 최적화의 존재 가능성을 부정하고 싶지 않다. 그것은 첫 번째 것 이후 스트렐린()에 대한 연속적인 호출을 최적화할 것이다.

는 매 번될 것이다.for. 의 결과를 의 결과를 메모하기 위해strlen(ss)컴파일러에게 전화해서 적어도 그 정도는 알아둘 필요가 있을 것이다.

  1. 그 은 할 수 없다.strlen부작용이 없었다.
  2. 기억은 다음을 가리켰다.ss루프가 지속되는 동안 변하지 않음

컴파일러는 이 두 가지를 모두 알지 못하므로 첫 번째 통화의 결과를 안전하게 메모할 수 없음

. 스트렐런은 늘 때마다 계산될 거야.

루프에 있는 ss를 변경하지 않으면 논리에 영향을 주지 않는다는 것을 의미한다.

다음 코드를 사용하는 것이 더 안전하다.

int length = strlen(ss);

for ( int i = 0; i < length ; ++ i )
{
 // blabla
}

네, 더.strlen(ss)각 반복마다 길이를 계산한다.만약 당신이 증가한다면ss어떤 식으로든 그리고 또한 더 많은i; 무한한 고리가 있을 것이다.

네, 더.strlen()기능은 루프를 평가할 때마다 호출된다.

효율성을 향상시키려면 항상 로컬 변수에 있는 모든 항목을 저장해야 함을 기억하십시오.시간이 걸리겠지만 매우 유용하다.

다음과 같은 코드를 사용할 수 있다.

String str="ss";
int l = strlen(str);

for ( int i = 0; i < l ; i++ )
{
    // blablabla
}

strlen(ss)코드가 실행될 때마다 계산될 것이다.

요즘은 흔하지 않지만 20년 전 16비트 플랫폼에서는 다음과 같이 추천한다.

for ( char* p = str; *p; p++ ) { /* ... */ }

컴파일러가 최적화에 그다지 똑똑하지 않더라도 위의 코드는 아직 조립 코드가 양호할 수 있다.

응. 테스트에서는 s가 루프 안에서 바뀌지 않는다는 것을 몰라.만약 당신이 그것이 변하지 않을 것이라는 것을 안다면 나는 다음과 같이 쓸 것이다.

int stringLength = strlen (ss); 
for ( int i = 0; i < stringLength; ++ i ) 
{
  // blabla 
} 

아흐, 이상적 상황하에서도 그럴 것이다, 바보야!

오늘(2018년 1월) 현재 및 gcc 7.3 및 cang 5.0을 컴파일할 경우:

#include <string.h>

void bar(char c);

void foo(const char* __restrict__ ss) 
{
    for (int i = 0; i < strlen(ss); ++i) 
    {
        bar(*ss);
    }
}    

이제 다음과 같은 이점을 얻을 수 있다.

  • ss일정한 포인터다.
  • ss표시가 되어 있다__restrict__
  • 루프 본체는 어떤 방법으로도 다음에 의해 가리킨 기억을 건드릴 수 없다.ss(글쎄요, 만약 그것이 그 법을 위반하지 않는 한,__restrict__).

그래도 두 컴파일러 모두 실행해strlen() 그 고리의 모든 반복을 말이야대박이다.

이것은 또한 @Praetorian과 @JaredPar의 암시/우울한 생각이 밖으로 튀지 않는다는 것을 의미한다.

네, 간단히 말하면. 없다. 만약 이 Dhouldo의 변경사항이 없다는 것을 말이다.ss그러나 안전한 상태에서는 YES라고 생각해야 한다.와는이 되다)와이 있다.multithreaded이벤트 중심 프로그램, NO라고 생각하면 버그가 생길 수 있다. 프로그램 복잡성을 크게 개선하지 않을 테니 안전하게 놀아라.

strlen()하여 마시다i증가 및 최적화되지 않음.

아래 코드는 컴파일러가 최적화하지 않아야 하는 이유를 보여준다.strlen().

for ( int i = 0; i < strlen(ss); ++i )
{
   // Change ss string.
   ss[i] = 'a'; // Compiler should not optimize strlen().
}

우리는 그것을 쉽게 테스트할 수 있다.

char nums[] = "0123456789";
size_t end;
int i;
for( i=0, end=strlen(nums); i<strlen(nums); i++ ) {
    putchar( nums[i] );
    num[--end] = 0;
}

루프 조건은 루프를 다시 시작하기 전에 각 반복 후에 평가한다.

또한 문자열의 길이를 다룰 때 사용하는 유형도 주의하십시오. 그것은 다음과 같아야 한다.size_t로 정의되어 있는unsigned int정각으로에 비교하고 캐스팅하다.int심각한 취약성 문제를 일으킬 수 있다.

글쎄, 나는 누군가가 그것이 어떤 "깨끗한" 현대 컴파일러에 의해 기본적으로 최적화되어 있다고 말하고 있다는 것을 알아차렸다.그런데 최적화 없이 결과를 본다.나는 노력했다:
최소 C 코드:

#include <stdio.h>
#include <string.h>

int main()
{
 char *s="aaaa";

 for (int i=0; i<strlen(s);i++)
  printf ("a");
 return 0;
}

마이 컴파일러: g++(우분투/리나로 4.6.3-1우분투5) 4.6.3
g pp블리리리리리리리리:::: g++ -s -masm=intel test.cpp

Gotten assembly code at the output:
    ...
    L3:
mov DWORD PTR [esp], 97
call    putchar
add DWORD PTR [esp+40], 1
    .L2:
     THIS LOOP IS HERE
    **<b>mov    ebx, DWORD PTR [esp+40]
mov eax, DWORD PTR [esp+44]
mov DWORD PTR [esp+28], -1
mov edx, eax
mov eax, 0
mov ecx, DWORD PTR [esp+28]
mov edi, edx
repnz scasb</b>**
     AS YOU CAN SEE it's done every time
mov eax, ecx
not eax
sub eax, 1
cmp ebx, eax
setb    al
test    al, al
jne .L3
mov eax, 0
     .....

프루토리안의 대답을 상세히 설명하면서 나는 다음과 같은 것을 추천한다.

for( auto i = strlen(s)-1; i > 0; --i ) {foo(s[i-1];}
  • auto어떤 종류의 strlen이 돌아오는지 신경쓰고 싶지 않기 때문이다.C++11 컴파일러(예:gcc -std=c++0x완전히 C++11이 아니라 자동 타입이 효과가 있다)가 그것을 해 줄 것이다.
  • i = strlen(s)비교하고 싶기 때문에0(아래 참조)
  • i > 0왜냐하면 0과의 비교는 다른 숫자와 비교하는 것이 더 빠르기 때문이다.

단점은 사용해야 한다는 것이다.i-1문자열 문자에 접근하기 위해.

참조URL: https://stackoverflow.com/questions/11365039/will-strlen-be-calculated-multiple-times-if-used-in-a-loop-condition

반응형