Pointer confusion

I imagine that a lot of people do what I do, in that we use snippets of code from examples without understanding how they work hoping that the understanding will come later.

I'm trying to understand pointers and I am struggling. I would be really grateful if somebody could explain the following.

In this line:

esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

I am confused by (uint8_t *) &myData , it seams to me to be a mismatch. From what I have read, uint8_t* is a pointer to an unsigned integer and &myData is the address of a struct structure which contains varying variable types. I don't understand the interaction of (uint8_t *) &myData.

Any help would be much appreciated.

1 Like

A struct is just like a variable. It is a combination of variables, packed together as a single variable.

The function esp_now_send() needs a pointer to a memory location and a integer for the number of bytes.

The address of a variable can be obtained with '&'.

int i = 5;
int * p;  // create a pointer
p = &i;   // point to i

A pointer to the memory location where the struct data is, is not enough. The pointer has to be converted to a different pointer. It is still the same pointer with the same value, but the function needs a different pointer (different in syntax, the same in binary compiled code).

In the past a void pointer was often used: void *.
It means a pointer to "something" or "anything" or "whatever".

I hope others have a different look at it, so you can choose which explanation you like the best :wink:

Close. The function needs a different datatype.
C++ is a strongly typed language and only performs implicit type conversion according to certain rules.

In many cases the programmer must explicitly tell the compiler what datatype conversion to use. In this case esp_now_send() needs a pointer to a uint8_t (i.e. datatype 'uint8_t *'); But, the user wants to send myData (which is of some type we don't know because @iangill didn't show us enough of the code). The '(uint8_t *)' syntax is a "cast" that tells the compiler to treat '&myData' as a 'uint8_t *'.

1 Like

Not a bash (so of course expect a different view) but;

You would serve yourself much better getting solid with the code you use that you don't get.. YET. This is because in doing so you will learn to read code for comprehension and write same with confidence.

Pointers are great but you need to know better what you would point to. More simply, you need to practice and break a few sketches to fix and learn more than reading books alone show. You still need the books (skash web pages) but only to get started and refer to AS you learn.

The full struct is

typedef struct struct_message {
  char a[32];
  int b;
  float c;
  bool d;
} struct_message;

// Create a struct_message called myData
struct_message myData;

It's from:

https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/

I still don't understad where the uint8_t comes in, or is this just to store the size in bytes of the data?

This is generally what I am trying to do. I trying to understand examples.

The paradox is that examples are often created by experianced coders, making example sketches dificult to ubderstand for newbies. But starting without examples, especially where libraries are involved would be like trying to climb mount everest, in flip flops and spedos.

1 Like

presumably the arguments to esp_now_send() are an address, a pointer to sequence of bytes and the number of bytes to send.

you want to send your struct_message. providing a pointer to your struct_message would be an error.

so the (uint8_t*) is called a cast where you're telling the compiler to override the variable type to avoid the error.

Right.
Looking in esp_now.h, you'll find the function's prototype:

esp_err_t esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len);

Note that the type of the second parameter is 'const uint8_t *'

No, 'sizeof(myData)' the size in bytes of the data.

I understand the above argument as follows in an 8-bit Arduino UNO Platform.

1. The myData component is a memory space (I assue that it is an array) whose items are 8-bit wide (hence: uint8_t = byte) and the base address of the array is in a pointer variable (hence: * is with (uint8_t*) = the cast). Demonstartions codes:

byte myData[] = {0x12, 0x34};  //uint8_t myData[] = {0x12, 0x34};

void setup() 
{
  Serial.begin(9600);
  byte *ptr;//ptr is a pointer variable containing base address of a byte-type memory space 
  ptr = (byte*)&myData;  //base address is passed into ptr variable
  byte m = *ptr; // m = 0x12
  Serial.println(m, HEX); //shows: 12 
}

void loop() {}

2. If myData is an array of integers (datae items are 16-bit), then the beginning address of the array space would be passed to a pointer variable by the execution of the following code:

int *ptr;  //int16_t *ptr
ptr = (int*)&myData;

3. if myData is a 32-bit memory space (the single data item is 32-bit), then the beginning address of the memory space would be passed to a pointer variable by the execution of the following code:

long y = 0x12345678;
long *ptr;    //int32_t *ptr;
ptr = (long*)&y;
long m = *ptr;
Serial.println(m, HX); //shows: 12345678

What advantage is there in using pointers, there must be one.

All the examples that I have looked at just appear to do exacltly the same thing as using normal variables. It appears that using pointers just complicates matters for no apparent reason. But there must be a reason or they wouldn't exist.

I write examples for beginners but not down to just started.
Beginners can be ABC's or words then sentences... grade school to 6th equivalent in code. For some it's slow pitch while some are at T-ball.

We have all done grade school just to be here so we know the drill of starting simple with what we call simple and work up.

I try and make my examples as to the point as possible but for you it is all reaching up from the ground of what you know. You might need an intro and even learn some interpreter Basic (not compiled!) that lets you try things out way eqsier/faster... just don't pour a year into Basic unless you don't like yourself, learn to where C makes sense (much less to learn than C++) and then tackle Arduino Examples.

In this case, it allows sending a data structure of any type / size. All that needs be supplied is the address of the data (cast to a 'uint8_t *') and the number of bytes to send.

There are plenty of good references to learn about pointers. Try some internet searches or buy a good programming book.

You don't begin to know possibly how much pointers you use already.

If you use arrays, the name of the array is a pointer.

x[12] is the same thing as x+12. Pointers let us do address math even when we might not know it. Pointers are power tools that beginners should learn when ready to not be beginners any more.
Can you do without them? Sure. But you may type a lot more code!

There are even pointers to functions. A value in a variable can determine what function is used in a line of code. A table of those can make a base for an interpreter without huge code.

Pointers are Under The Hood stuff that the language you use depends on.

besides being able to directly specify the address of hardware registers,
Niklaus Wirth described the used of pointers in Algorithms + Data Structures = Programs to used pointers to create linked lists and trees to dynamically relate pieces of data to more efficiently access it, amoung many other uses

Not the best programming book I've ever run across, IMO. Especially the program examples ... mostly snippets with single-letter variable names.

my understanding is it was the book where pointers were first described and proposed the Pascal language for their use. the book also has code for a Pascal compiler

All that could be true. I did say IMO, which is based solely on it being the text for at least one undergraduate programming courses that I took ... more years ago than I care to admit.

yes you did.

but this wasn't necessarily a book for teaching how to use linked lists. i think it was more to explain a new programming concept

@iangill

@iangill You can experince the advantage of using pointer variable in copying the contents of Table-1 into Table-2 of Fig-1 with the understanding that arithmetic operations can be done on pointer variable as @GoForSmoke has mentioned in post #13.


Figure-1:

and there, my friend, is the downfall - many people give examples without sufficient context, leaving the asker more confused than before. I'm not pointing fingers, I've done it as well.
It's hard to put our heads in the head of a novice when he/she hasn't given us the first clue about any programming experience. If you come to me and say 'all I've ever programmed in is Basic, what's this pointer stuff ', it's a whole lot easier than 'what's this pointer stuff" with zero frame of reference.