제한을 가하다

restrict

C 프로그래밍 언어에서,restrict포인터 선언에 사용할 수 있는 키워드 입니다.프로그래머는 이 형식 한정자를 추가함으로써 포인터 수명 동안 포인터 자체 또는 포인터에서 직접 파생된 값(예:pointer + 1)는 그것이 가리키는 객체에 접근하기 위해 사용된다.null

restrict최적화를 지원하는 포인터 앨리어싱의 효과를 제한한다.의향선언을 따르지 않고 독립된 포인터로 객체에 접근하면 정의되지 않은 동작이 발생한다.이 형식 한정자를 사용하면 C 코드는 포트란에서 작성된 프로그램과 동일한 성능을 얻을 수 있다.C99 규격에 도입되었다.[1]

C++에 대한 표준 지원이 없음restrict, 그러나 많은 컴파일러들은 GCC의 것과 같은 C++와 C 둘 다에서 작용하는 등가물을 가지고 있다.__restrict__, 및 Visual C++__declspec(restrict). 게다가__restrict그 세 명의 컴파일러가 지지한다.이러한 대체 키워드에 대한 정확한 해석은 컴파일러에 따라 다르다.

  • GCC와 캉과 같은 유닉스 스타일의 컴파일러에서는__restrict그리고__restrict__C의 상대와 정확히 같은 의미를 갖는다.확장에는 참조 유형에 적용할 수 있도록 허용하는 것이 포함된다.this.[2]
  • Visual C++에서는 다음과 같은 여러 개의 무별칭 한정자가 제공된다.
    1. __declspec(restrict)함수 선언에 적용되며 반환된 포인터가 앨리어싱되지 않았음을 암시한다.
    2. __restrict와 같은 장소에서 사용된다.restrict, 그러나 no-messages 힌트는 에 있는 것처럼 전파되지 않는다.restrict. 조합형에도 연장된다.

최적화

컴파일러가 메모리 블록에 포인터가 하나만 있다는 것을 알면 더 최적화된 코드를 만들 수 있다.예를 들어,

공허하게 하다 updatePtrs(size_t *ptrA, size_t *ptrB, size_t *발랄하게 하다) {   *ptrA += *발랄하게 하다;   *ptrB += *발랄하게 하다; } 

위의 코드에서 포인터는ptrA,ptrB그리고val 컴파일러가 최적 코드를 생성하지 않도록 동일한 메모리 위치를 가리킬 수 있음:

; 가상 RISC 기계. ldr r12년, [발랄하게 하다]     ; r12에 val에서 메모리를 로드한다. ldr r3, [ptrA]     ; ptrA에서 r3으로 메모리를 로드한다. 덧셈을 r3, r3, r12년    ; 추가 수행: r3 = r3 + r12 발을 동동 구르다 r3, [ptrA]     ; r3을 메모리 위치 ptrA에 저장하여 값을 업데이트하십시오. ldr r3, [ptrB]     ; 'load'는 앞의 'store'가 완료될 때까지 기다려야 할 수 있다. ldr r12년, [발랄하게 하다]     ; 일관성을 보장하기 위해 한 번 더 로딩해야 한다. 덧셈을 r3, r3, r12년 발을 동동 구르다 r3, [ptrB] 

그러나 만약 그렇다면.restrict키워드를 사용하고 위의 함수를 다음과 같이 선언함

공허하게 하다 updatePtrs(size_t *제한을 가하다 ptrA, size_t *제한을 가하다 ptrB, size_t *제한을 가하다 발랄하게 하다); 

컴파일러는 다음과 같이 가정할 수 있다.ptrA,ptrB그리고val다른 위치를 가리키고 한 포인터가 참조하는 메모리 위치를 업데이트하면 다른 포인터가 참조하는 메모리 위치에 영향을 주지 않는다.컴파일러가 아닌 프로그래머는 포인터가 동일한 위치를 가리키지 않도록 할 책임이 있다.컴파일러는 예를 들어 코드를 다시 정렬하고, 먼저 모든 메모리 위치를 로드한 다음, 결과를 메모리로 커밋하기 전에 작업을 수행할 수 있다.null

ldr r12년, [발랄하게 하다]  ; val은 이제 한 번만 로드된다는 점에 유의하십시오. ldr r3, [ptrA]  ; 또한, 모든 '적재'는 시작에 있다. ldr r4, [ptrB] 덧셈을 r3, r3, r12년 덧셈을 r4, r4, r12년 발을 동동 구르다 r3, [ptrA]  결국엔 가게가 다 있어 발을 동동 구르다 r4, [ptrB] 

위 조립 코드는 다음과 같은 이유로 더 짧다.val한 번만 장전된다.또한 컴파일러는 코드를 더 자유롭게 재배열할 수 있기 때문에 컴파일러는 더 빨리 실행되는 코드를 생성할 수 있다.위의 예제의 두 번째 버전에서는store모든 작전은 다음 날 이후에 행해지고 있다.load운영(프로세서가 코드 중간에서 차단할 필요가 없도록 함)store작전이 완료되었다.null

실제 생성된 코드는 동작이 다를 수 있다는 점에 유의하십시오.위의 미니 예제를 통한 이점은 작은 경향이 있으며, 실제의 경우 무거운 메모리 액세스를 수행하는 큰 루프는 제한을 통해 실제로 도움을 받는 경향이 있다.null

위에서 언급했듯이, 잘못된 코드가 어떻게 작용하는지는 정의되지 않으며, 컴파일러는 코드가 의도된 선언을 따르는 경우에만 생성된 코드가 제대로 작동하도록 보장한다.null

컴파일러 경고

잘못된 코드를 방지하기 위해 일부 컴파일러 및 기타 도구는 매개 변수가 표시된 함수에 중복 인수가 전달되었을 때 탐지하려고 시도한다.restrictCERT C 코딩 표준은 의 오용을 고려한다.[3]restrict소프트웨어 버그 발생 가능성이 높은 출처(EXP43-C)가 표시된 라이브러리 기능도 포함되지만, 2019년 11월 현재 이로 인해 취약성이 발생한 것으로 알려져 있지 않다.[4]

참조

  1. ^ Ulrich Drepper (October 23, 2007). "Memory part 5: What programmers can do". What every programmer should know about memory. lwn.net. ...The default aliasing rules of the C and C++ languages do not help the compiler making these decisions (unless restrict is used, all pointer accesses are potential sources of aliasing). This is why Fortran is still a preferred language for numeric programming: it makes writing fast code easier. (In theory the restrict keyword introduced into the C language in the 1999 revision should solve the problem. Compilers have not caught up yet, though. The reason is mainly that too much incorrect code exists which would mislead the compiler and cause it to generate incorrect object code.)
  2. ^ "Restricted Pointers". Using the GNU Compiler Collection (GCC).
  3. ^ "Warning Options: -Wrestrict". GCC. Retrieved 19 November 2019.
  4. ^ "EXP43-C. Avoid undefined behavior when using restrict-qualified pointers". SEI CERT C Coding Standard. Retrieved 19 November 2019.

외부 링크