2016-10-25 60 views
1

我已經寫下了環形緩衝區的代碼。我只想使用沒有任何位置指示器的指針。但是我在寫作時沒有得到預期的結果。雖然寫入發生,但它不會在第一次進入後停止。它繼續下去。閱讀操作似乎是正確的。 我試圖使用調試器進行調試。但令我驚訝的是,if(head>(myRing+AVAILABLE_SIZE*sizeof(myRing[0])))沒有在函數writeToRing()函數中執行。調試器正在跳過這一步。也是第一次在這個函數中頭++沒有被執行,代碼將首先轉到if(head == tail)然後回到頭++;無法找到原因。 我使用的代碼:: Blocks的使用MinGW使用直接指針操作實現環形緩衝區的問題

#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); 
} 

編輯: 更新了另一種方法的代碼。在這段代碼中,一個數據字節不會被浪費。我測試過,似乎正在工作。但如果還有其他問題,請告訴我。對於類型說明符%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)。當headtail等於wrap時,是時候將它們設置回緩衝區的開始。

  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,因爲這是針對嵌入式代碼的,並且溢出不太可能。所以考慮到沒有溢出的機會,我認爲撤消「頭」可能不會出現,因此可以避免額外的複製和額外的內存。還要進行調試:即使在刪除優化之後,也沒有運氣。我需要去eclipse,看看是否解決了這個問題(不確定調試時特別需要的其他編譯器設置) – Rajesh