2016-10-25 12 views
1

다음은 링 버퍼에 대한 코드입니다. 나는 위치 표시기없이 포인터 만 사용하기를 원했습니다. 그러나 나는 글쓰기 동안 기대되는 결과를 얻지 못하고있다. 쓰기가 발생하지만 첫 번째 항목 이후에 중지되지 않습니다. 그것은 더 계속됩니다. 읽기 작업이 올바른 것 같습니다. 디버거를 사용하여 디버깅을 시도했습니다. 그러나 놀랍게도 if(head>(myRing+AVAILABLE_SIZE*sizeof(myRing[0])))은 writeToRing() 함수에서 실행되지 않습니다. 디버거가이 단계를 건너 뜁니다. 또한 처음으로 ++ ++는이 함수에서 실행되지 않고 대신에 if (head == tail)로 이동 한 다음 ++ ++로 되돌아갑니다. 이유를 찾을 수 없습니다. 나는 직접 포인터 조작을 사용한 링 버퍼 구현 관련 문제

#define MAX_SIZE 2 
#define AVAILABLE_SIZE (MAX_SIZE-1) 

/* 
Program to construct and access ring buffer without structure. 
This program makes use of pointer. Even without pointer it is possible to manage 
*/ 

int myRing[MAX_SIZE]; 
int *head=myRing; // Initialize next element than tail 
int *tail=myRing; 

enum ERROR_LIST 
{ 
    SUCCESS=0, 
    BUFFER_FULL=-1, 
    BUFFER_EMPTY=-2 
    }; 

int writeToRing(int data) 
{ 
    head++; 
    if(head>(myRing+AVAILABLE_SIZE*sizeof(myRing[0]))) 
    { 
     head=myRing; //wraps over 
    } 
    else 
    { 
     // Do nothing 
    } 
    if(head==tail) 
    { 
     head--; 
     if(head<myRing)  // In case head is less than starting address. assign max address 
     { 
      head=(myRing+AVAILABLE_SIZE*sizeof(myRing[0])); 
     } 
     printf("Buffer full\n"); 
     return(BUFFER_FULL); 
    } 
    else 
    { 
     *head=data; 
    } 
    return(SUCCESS); 
} 

int readFromBuffer(int* data) 
{ 
    if(tail==head) 
    { 
     return(BUFFER_EMPTY); 
    } 
    else 
    { 
     tail++; 
     if(tail>(myRing+AVAILABLE_SIZE*sizeof(myRing[0]))) 
     { 
      tail=myRing; 
     } 
     *data=*tail; 
     return(SUCCESS); 
    } 
} 

int main() 
{ 
    int option; 
    int data; 
    while(1) 
    { 
    printf("Enter Your option. 1 for writing to buffer, 2 for reading from Buffer\n"); 
    scanf("%d",&option); 
    if(option==1) 
    { 
     printf("Enter the data to be written\n"); 
     scanf("%d",&data); 
     if(writeToRing(data)) 
     { 
      printf("Buffer is Full. Remove the contents first\n"); 
     } 
    } 
    else if(option==2) 
    { 
     if(!readFromBuffer(&data)) 
     { 
      printf("The data read = %d\n",data); 
     } 
     else 
     { 
      printf("Buffer is Empty\n"); 
     } 
    } 
    else 
    { 
     printf("Invalid Option\n"); 
    } 

    } 
    return(0); 
} 

편집는 MinGW

와 코드 :: 블록을 사용하고 있습니다 : 다른 접근 코드를 업데이트했습니다. 이 코드에서는 하나의 데이터 바이트가 낭비되지 않습니다. 나는 테스트를했고 작동하는 것처럼 보인다. 하지만 다른 문제가있는 경우 알려 주시기 바랍니다. 유형 지정자 % u를 사용하는 scanf에 대해 두 가지 경고가 있으며이를 수정하는 방법을 알아야합니다. 기본적으로이 경우 바이트를 읽길 원합니다. 내가 정수 읽기를한다면 아무런 문제가 없다.

#include <stdio.h> 
#include <stdint.h> 
#define MAX_SIZE 3 

uint8_t BUFFER_FULL=0; // Initially buffer full flag is cleared 
uint8_t BUFFER_EMPTY=1; // Initially buffer empty flag is set 

/* 
Program to construct and access ring buffer without pointer. 
Also this makes use of full buffer and checks for buffer empty or buffer full condition 
before calling write or read functionality, 
*/ 

uint8_t myRing[MAX_SIZE]; 
uint8_t head=0; // Initialize the head 
uint8_t tail=0; // Initialize the tail 
uint8_t maxPosition= MAX_SIZE-1; 


void writeToRing(uint8_t data) 
{ 
    head=head+1; 
    if(head>maxPosition) 
    { 
     head=0; 
    } 
    else 
    { 
     // Do nothing 
    } 
    // Write the data to buffer 
    myRing[head]=data; 
    BUFFER_EMPTY=0; // Indicate that buffer is not empty 

    if(head==tail) 
    { 
     printf("Buffer full No further data can be written\n"); 
     BUFFER_FULL=1; 
    } 
} 

void readFromRing(uint8_t* data) 
{ 
    // Initially buffer is empty (BUFFER_EMPTY=1). At that point, calling portion cannot call this function. 
    // Later when data is written, writeToRing() function will clear BUFFER_EMPTY flag. 

    tail++; 
    if(tail>maxPosition) 
    { 
     tail=0; 
    } 
    *data=myRing[tail]; 
    // Once reading is done, ensure that BUFFER_FULL flag is cleared. 
    BUFFER_FULL=0; 
    if(tail==head) 
    { 
     printf("Buffer is now Empty. No further reading possible\n"); 
     BUFFER_EMPTY=1; 
    } 
} 

int main() 
{ 
    uint8_t option; 
    uint8_t data; 
    while(1) 
    { 
     printf("Enter Your option. 1 for writing to buffer, 2 for reading from Buffer\n"); 
     scanf("%u",&option); 
     if(option==1) 
     { 
      if(!BUFFER_FULL) 
      { 
       printf("Enter the data to be written\n"); 
       scanf("%u",&data); 
       writeToRing(data); 
      } 
      else 
      { 
       // Nothing to be done in case buffer is FULL 
       printf("Buffer should be cleared first\n"); 
      } 
     } 
     else if(option==2) 
     { 
      if(!BUFFER_EMPTY) 
      { 
       uint8_t data; 
       readFromRing(&data); 
       printf("The data read = %d\n",data); 
      } 
      else 
      { 
       printf("Buffer is Empty. Write something before you read\n"); 
      } 
     } 
     else 
     { 
      printf("Invalid Option\n"); 
     } 
    } 
    return(0); 
} 

답변

2

정확한 형태가 될 것이다 :

if(head>(myRing+AVAILABLE_SIZE)) 
{ 
... 
} 

myRing 포인터이므로는 "+"연산자는 소자 자체의 크기에 의한 승산을 수행한다.

+0

사실 저는 처음에 sizeof (int)를 곱하지 않고 시도했습니다. 그것은 나를 괴롭혔다. 그리고 나는 테스트 목적으로 바꾸었고 제거하는 것을 잊었다. 디버거가 내가 지시 한대로 단계를 건너 뛰는 이유를 모르겠습니다. 그러나 오늘 나는 당신의 제안에 따라 행동했으며 효과가 있습니다. 어딘가에 어리석은 실수를 했어야 만합니다. – Rajesh

1

는 그 링 버퍼의 끝을 표시하는 코드

  1. 다른 포인터 (wrap를) 추가를 단순화 할 수있는 몇 가지 개선 사항이 있습니다. headtailwrap 인 경우 버퍼의 시작 부분으로 다시 설정할 시간입니다.

  2. writeToRing 함수에서 임시 포인터 (temp)를 사용하여 버퍼가 가득 찼는 지 확인하십시오. 그런 식으로 head은 쓰기가 성공할 때까지 영향을받지 않으므로 계산을 실행 취소 할 필요가 없습니다.

디버거가 재미 행동 한 이유에 관해서는
int myRing[MAX_SIZE]; 
int *head = myRing; 
int *tail = myRing; 
int *wrap = &myRing[MAX_SIZE]; 

int writeToRing(int data) 
{ 
    int *temp = head+1; 

    if (temp == wrap) 
     temp = myRing; 

    if (temp == tail) 
     return BUFFER_FULL; 

    head = temp; 
    *head = data; 
    return SUCCESS; 
} 

int readFromRing(int *data) 
{ 
    if (tail == head) 
     return BUFFER_EMPTY; 

    tail++; 
    if (tail == wrap) 
     tail = myRing; 

    *data = *tail; 
    return SUCCESS; 
} 

, 디버깅 할 때 최적화 전원을 꺼주십시오. 디버거는 최적화 된 코드를 따르는 데 어려움을 겪습니다.

+0

이것은 임베디드 코드 용이며 오버플로가 발생하지 않으므로 temp를 추가하지 않았습니다. 오버플로가 발생할 가능성이 없다는 것을 고려할 때 "헤드"를 원상태로 돌릴 수 없으므로 여분의 복사와 여분의 메모리를 피할 수 있다고 생각했습니다. 또한 디버깅에 임함 : 최적화를 제거한 후에도 운이 없다. 이클립스에 가서이 문제가 해결되는지 확인해야한다 (디버깅을 위해 특별히 필요한 다른 컴파일러 설정은 확실하지 않음) – Rajesh