1

I have written below code for ring buffer. I wanted to use only pointer without any position indicator. But I am not getting expected result while writing. Though write happens, it does not stop after 1st entry. It continues further. Read operation seems to be correct. I tried to debug using debugger. But to my surprise, if(head>(myRing+AVAILABLE_SIZE*sizeof(myRing[0]))) is not getting executed in function writeToRing() function. Debugger is skipping this step. Also first time head++ is not getting executed in this function, instead code will first go to if(head==tail) and then come back to head++; Unable to find the reason. I am using Code::Blocks with 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); } 

Edit: Updated the code with another approach. In this code one data byte is not wasted. I tested and seems to be working. But in case there is any other issues, please let me know. There are two warnings for scanf with type specifier %u and need to see how to fix it. I basically want to read bytes in this case. If I go for integer read, there is no issue.

#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 Answers 2

3

The correct form would be:

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

Since myRing is a pointer, "+" operator performs the multiplication by element size in itself.

Sign up to request clarification or add additional context in comments.

1 Comment

In fact I had initially tried without multiplying by sizeof(int). It was troubling me and then I changed for testing purpose and forgot to remove. Not sure why debugger was skipping the step as I had indicated. However today I did as per your suggestion and it is working. Must have done some silly mistake somewhere.
2

There are a couple improvements that you can make that will simplify the code

  1. Add another pointer (wrap) that marks the end of the ring buffer. When head and tail are equal to wrap, then it's time to set them back to the beginning of the buffer.

  2. In the writeToRing function, use a temporary pointer (temp) to check whether the buffer is full. That way head is unaffected until you know the write will succeed, so you don't need to undo the calculations.


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

As for why the debugger was acting funny, be sure that optimizations are turned off when you're debugging. Debuggers have a hard time following optimized code.

1 Comment

I did not add temp because this is for embedded code and overflow is unlikely. So considering there is no chance of overflow, I thought undoing "head" may not arise and hence extra copying and extra memory could be avoided. Also coming to debugging: There is no luck even after removing optimization. I need to go for eclipse and see if this issue solves (Not sure of any other compiler settings specifically needed for debugging)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.