2017-10-17 3 views
-1

Circular buffer incrementation 마지막 문장이 어떻게 포인터를 증가시키는 지 이해할 수 없습니다. 몇 가지 예를 들어 설명해 주시겠습니까? 도시 된 바와 같이대체 방법을 사용한 순환 버퍼 증가

+3

이것은 정말 나쁜 코드입니다. –

+0

2의 강점 때문에 비트 맵 (BUFFERSIZE-1)을 사용하여 오버플로되었을 때 인덱스를 0으로 롤백 할 수 있습니다. 코드 작성자는 모듈러스 연산자 또는 조건 분기를 사용하여 성능이 저하되는 것을 피하려고합니다. –

+0

그는 [BUFFERSIZE-1] (AND *) 대신 [BUFFERSIZE-1]과 직접 AND should하지 않아야합니까? –

답변

1

코드 :

aptr = (aptr + 1) & (void *)(BUFFERSIZE - 1); 
    // |________| incremented here 

는 원형 버퍼는 버퍼의 크기가 2의 거듭 제곱은 다음 & 간단히 마스킹 롤오버하는 쉽고 빠른 방법 때문이다. 그런 다음, BUFFERSIZE256이라고 가정하면 : 선택

num & (257 - 1) != num % 257 
num & (0x101 - 1) != num % 0x101 
num & 0x100 != num % 0x101 

(void *) 허용 컴파일러 :

num & (256 - 1) == num % 256 
num & (0x100 - 1) == num % 0x100 
num & (0x0ff) == num % 0x100 

수는 2의 거듭 제곱 아닙니다

, 당신은 마스킹 기술을 사용할 수 없습니다 포인터 너비에 따라 BUFFERSIZE 상수의 적절한 너비 ... 일반적으로 알고있는 것이 가장 좋습니다 -! - 다음과 같은 명령문 앞에 오는 너비.

&이 에뮬레이트 된 롤오버 이벤트를 발생시키는 이유를 분명히하기 위해 16 진법을 추가했습니다. 0xff은 이진수 인 0x11111111이므로 AND 연산은 단순히 상위 비트를 마스킹하는 것입니다.

+0

제 의심은 num이 ANDED (void *) (BUFFERSIZE-1)입니다. 실제로 포인터 타입으로 num을 덧붙이면 일반 정수가 아닌 num을 직접 (256-1) 사용할 수 있습니다. 내 가정은, 그것이 num & & nbsp; (BUFFERSIZE-1) 였으면, 당신이 말하는 최종 답을 얻었을 것입니다. –

+0

'aptr '은 어떤 종류의 포인터, 즉'uint16_t * aptr'로 선언되었을 것입니다.이 경우에는 유효합니다. – slightlynybbled

+1

포인터 값을 bitwise에 전달하면 [제약 조건 위반] (http://port70.net/~nsz/c/c11/n1570.html#6.5.10p2)이므로 진단이 생성되어야합니다. –

1

2이 방법의 문제점.

가) 비트 단위 연산과 함께 포인터를 사용하는 것은 이식성이없는 코드입니다. charBUFFERSIZE보다 넓은 개체에 aptr 점은 버퍼의 원소의 개수 인 경우 char *와 유사한 void *의 비표준 연산을 지원 컴파일러 @Ilja Everilä

char *aptr; 
    // error: invalid operands to binary & (have 'char *' and 'void *') 
    // The following increments the index: (not really) 
    // aptr = (aptr + 1) & (void *)(BUFFERSIZE-1); 

B)는 수학 잘못 바이트 크기가 아닙니다. 물론 비표준 컴파일러가 some_type * & void *을 구현하는 방법에 따라 다릅니다. 일부 구현 특정 동작을 사용하기 위해 불필요하게 코딩하는 것은 왜 까닭입니까?


대신 i % BUFFERSIZE을 사용하십시오. 이 휴대용 접근 방식은 BUFFERSIZE이 2의 거듭 제곱이고 잘되지 않을 때 작동합니다. 컴파일러가 i % power-of-2i이 부호없는 유형 인 경우에는 동일한 코드가 확실히 i & (power-of-2 - 1)으로 생성됩니다.

이 최적화를 인식하지 못하는 컴파일러의 경우 더 나은 컴파일러를 고려해야합니다.

#define BUFFERSIZE 256 
int main(void) { 
    char buf[BUFFERSIZE]; 

    // pointer solution 
    char *aptr = buf; 
    aptr = &buf[(aptr - buf + 1) % BUFFERSIZE]; 

    // index solution 
    size_t index = 0; 
    index = (index + 1) % BUFFERSIZE; 
}