Hi. I generally understand whats happening here with this code, but I have 2 questions. 1, *cp = (char)Serial.read(); what is going on with the (char)? this seems to be a part of the syntax I am unfamiliar with and I'm unsure why (char) is there or what it is doing. 2nd, does the pointer always iterate through a char array one char at a time? Thanks!!
bool readSerial(void)
// Read a line from the serial monitor and return true when the eoln is detected.
{
static char* cp = mesg;
bool gotNewData = false;
while (Serial.available())
{
*cp = (char)Serial.read();
if ((*cp == '\n') || (cp - mesg >= MSG_BUF_SIZE - 2)) // end of message character or full buffer
{
*cp = '\0'; // end the string
// restart the index for next filling spree and
// flag we have a message waiting
cp = mesg;
gotNewData = true;
}
else // move char pointer to next position
cp++;
}
return(gotNewData);
}
In this case, because it's a char pointer, yes. A pointer iterates an amount depending on its declared type. So an int pointer will increment/decrement by an int, a char* by char, etc.
I was not aware of this, really appreciate this info. If i can ask one more question... when does the mesg variable acquire the serial reading data here? I think the *cp vs cp is throwing me off. Thanks again!!
Rather than using a buffer pointer and calculating an index with cp - mesg, you can use a buffer index:
bool readSerial(void)
// Read a line from the serial monitor and return true when the Newline is detected.
{
static mesgIndex = 0;
bool gotNewData = false;
while (Serial.available())
{
mesg[mesgIndex] = Serial.read();
if ((mesg[mesgIndex] == '\n') || (mesgIndex >= MSG_BUF_SIZE - 2)) // end of message character or full buffer
{
mesg[mesgIndex] = '\0'; // end the string
// restart the index for next filling spree and
// flag we have a message waiting
mesgIndex = 0;
gotNewData = true;
}
else // move char pointer to next position
mesgIndex++;
}
return gotNewData;
}
This seems much more readable to me. I'm wondering why the original code would've been written how it was, and if there's any real difference in functionality doing it your way.
Sometimes it's a matter of style, other times there may be more code that is more easily understood that way. I have code I wrote many years ago that looks almost identical to what you posted. The logic of what I was doing at the time "fit" better with pointers than array indexes.
An array is actually just a pointer to the location where the contents of the array are being stored.
I too find it easier to read the array notation.
The indexing is built in and is easy to see.
The reason why pointers need to have a type (or void) is that the compiler does not know how to step through the array of numbers.
On an Uno, a char and byte are 1 byte, int is 2 bytes and long is 4 bytes.
So, an array of 5 chars will be 5 bytes long, and the compiler will need to add 1 to the address to get the address of the next item.
However, an array of 5 longs will take 20 bytes. If the first item is stored at address x, the next item will be stored at x+4, then x+8, etc, stepping by 4 at a time. By specifying what type of items we are storing there, the compiler is able to determine how to step to the next item.
Therefore, we can just say get me the 4th item, and not worry about the exact memory location of that item.
BTW, don't forget to specify the type of the array for the code example above:
This is helpful, thanks so much for the explanation. I guess a big part of my confusion in this code snippet is the he used both *cp and cp without the asterisk. I only see one cp ever declared in the entire program and its in this function.
The asterisk "*" here is declaring cp as a pointer. The pointer type is "char." The compiler needs to know this so it can index the pointer correctly. The pointer is initialized to point to the variable (array) called "mesg."
static char* cp = mesg;
This line says "put the value from Serial.read() into the location that cp is pointing to (the first location of mesg)."
*cp = (char)Serial.read();
I think that part of the confusion around pointers is that the "*" means different things when the variable is declared vs when it's actually used.
Now we will increment the pointer to point to the next memory location. Since it's a char type, the pointer will index by one byte (this is sometimes useful to know). Notice that we don't use the "*" here as that would change the meaning of the statement. The pointer is now pointing to the second location of mesg.
I read the declaration of a pointer like this:
read the identifier first (name);
then what is immediately to the right,
then to the left, and so on, back and forth
char* messageSent [10] = {};
I would read it as: messageSent is an array of 10, and is a pointer of char type.
It contains the address of the first item of the array.
*messageSent [2]
Now this is read as: value at the address pointed to by messageSent, indexed 2.
So, for example, if the first item (index 0) is stored at memory address 0xFF23, the value of interest will be found (by the compiler) at address 0xFF23+2. The pointer itself contains 0xFF23.
This actually made it finally click for me I think. So it's basically like pressing the right arrow key in text and watching the cursor go over one letter each time. You are much appreciated sir