Help in understanding pointers and references

Here is a snippet of my code (taken from an example in the ethershield library).

static uint8_t buf[551];
Serial.println((char*)&buf[5]);

In case you're unfamiliar, uint16_t is an unsigned 16 bit integer or "word" and uint8_t is the same as "byte" which is an 8 bit unsigned integer.

It's the 3rd line that I don't understand. My c++ is too rusty to read this. buf[] is an array. So buf[5] will be the 6th element in that array. I get confused what the (char*) command does. I'm guessing it's a pointer? Also is it trying to get the reference of buf[5] and that's what the & symbol means? So is trying to look at the pointer of a reference (redundant right?) then converting it to a character? Why would it need to be a char when it's just going to print it?

Any help at understanding what the * or & symbols mean in this statement is appreciated.

Assuming buf contains a string, all it is doing is printing the string starting from the 6th character. The address of buf[5] is of type pointer to uint8_t, so simply cast it to a pointer to char.

I’m pretty sure buf contains multi line strings, but this is strange to me because it’s declared as an integer.

Suppose I have this: buf = “/n/n891/n/n”
And I want to extract the value in 3rd line “891” from the variable. How would I go about doing it? The code above is basically stepping through each letter and printing it.

The code above is basically stepping through each letter and printing it.

I'm not sure what you're saying here, but to me it is printing shorter and shorter sub-strings, since println will always print until it finds \0, and there is only one of those right at the end.

It's the 3rd line that I don't understand

I can't help but notice that there are only two lines. Why don't you just show the rest of "my code"?

Well I was trying to simplify everything. Here is the function in consideration. Above when I said I don't understand the 3rd line I meant to say the 2nd line.

void browserresult_callback(uint8_t statuscode,uint16_t pos){
 if (pos != 0)
 {
  uint16_t pos = datapos;
  while (buf[pos]) // loop until end of buffer (or we break out having found what we wanted)
  {
    while (buf[pos]) if (buf[pos++] == '\n') break; // find the first line feed
    if (buf[pos] == 0) break; // run out of buffer
    if (buf[pos++] == '\r') break; // if it is followed by a carriage return then it is a blank line (\r\n\r\n)
   }
  if (buf[pos]) // we didn't run out of buffer
  {
   pos++; //skip over the '\n' remaining
   Serial.println((char*)&buf[pos]);
  }
 }
}
void browserresult_callback(uint8_t statuscode,uint16_t pos){
 if (pos != 0)
 {
  uint16_t pos = datapos;

Having two "pos" is a recipe for misunderstanding.

This is a case of odd looking casts to take advantage of some C++ function overloading and how the C standard deals with different 8 bit declarations.

The function println() can take different type of arguments. Depending on the type of argument it behaves differently.

In this case, the code appears to be wanting to print a C string. In C, strings are characters terminated by a Null.

The way to get the println() function to print a C string is to pass it a pointer to a char (char *) which is the first character of the string to be printed.

The tricky part in this case is that buf[] is declared as a uint8_t and not a char

Had the buffer been declared as a char, i.e: char buf[551];

Then to pass a pointer to a C string that starts at offset 5 you would have simply done:

Serial.println(&buf[5]);

Which means pass the address of the elemenat at index 5

note: buf[5] is the character &buf[5] is the address of that character at buf[5]

But since buf[] is a uint8_t if we passed &buf[5] that it would end up passing a pointer to a uint8_t (BTW uint8_t is really a typecast an unsigned char) also note: chars are different from "unsigned chars" and "signed chars". The C standard defines the 3 as being distinctly unique.

Since the print class wants to see a pointer to char and not a pointer to a uint8_t/"unsigned char" you must do a cast to override the definition of buf[] to get the println function to print a C string.

So Serial.println((char*) &buf[5]) means "I know buf[] is not an array of "char" and but I'm telling you that the resulting pointer &buf[5] shall be (char *) or a pointer to a char instead of a pointer to a "uint8_t" which is actually an unsigned char.

hope that helps.

--- bill

Bill this helped tremendously! You are a super charm!

I guess my only complaint now is why in the example sketch for the ethernet shield library is such a obscure and goofy way to print something. I'm doing something similar and I'm pretty sure I can simplify this code quite a lot.

Hrm. After studying this code for the weekend I still am stumped on something.

If I do Serial.println((char*) &buf[287]); I get this in return:

3 887

That's 3 lines total, the last one is blank. I want to assign a variable the value of the middle line, "887". The question now becomes, how do I go to the 2nd line of this pointer, extract the data, convert it to integer and assign it to a variable?

This is literally the last bit of code I have left in this program. I just can't seem to get this string value into a usable variable. Any ideas would be greatly appreciated!

The question now becomes, how do I go to the 2nd line of this pointer,

I can't see what your input looks like, but guessing that "2nd line" is a clue. Look for a carriage-return character after the last numeric character on the first line, then read your substring, stopping when you hit the first non-numeric character. When you say "usable variable" do you mean string or integer?

I would like to put the 2nd line into an integer because I need to control something based on that value. I could more than likely work with the data if I knew how to work with this really strange variable.

The buf[] var gets assigned in this cryptic esoteric way:

uint16_t dat_p;
int plen = 0;
plen = es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
dat_p=es.ES_packetloop_icmp_tcp(buf,plen);

es.ES_client_browse_url(PSTR(HTTPPATH), NULL, PSTR(HOSTNAME), &browserresult_callback);

Then the function browserresult_callback is pasted higher in this thread.

The thing is, I can't even say: char Str[ ] = {(char*)&buf[287]}; Because I get an error saying "initializer fails to determine size of 'Str'". And when I say Str[50] I get an error saying "invalid conversion from char* to char". I suppose I can do: char* Str[ ] = {(char*)&buf[287]}; But I'm not sure how to work with pointers well yet after that.

Got it. With a bunch of trial and error I was able to really simply extract the data I wanted with this code:

  char currentpower[6] = {buf[240], buf[241], buf[242], buf[243], buf[244], buf[245]};
    powernow = atoi(currentpower);

Thanks everyone! My project will be complete as soon as I get some LEDs in the mail and I'll let everyone see it. :)