Problem - using a Pointer in the library AikoEvents.h

Hi All,
i am trying to write an integer value in an function using a pointer. My problem is, that I don't know how to use pointers. The program is supposed to run the function hello once after a second and further print the value 46 (in this case). Here is my program:

#include <OneWire.h>
#include <AikoEvents.h>
using namespace Aiko;

void hello(int t) {
Serial.println(t);
}

void setup() {
Serial.begin(9600);
Events.addOneShotHandler(hello(void*)46, 1000); // --> any value
}
void loop() {
Events.loop();
}

Try this:

void hello() //No argument allowed
{
  ...
}
...
Events.addOneShotHandler(hello, 1000);

Thank you very much for the fast answer!
Is there anyway to allow an argument?

No, but you can use a global variable instead:

int helloArg;

void hello()
{
  //Use helloArg here..
}

//Set helloArg and event
helloArg = 46;
Events.addOneShotHandler(hello, 1000);

Danois90:
No, but you can use a global variable instead:

...which defeats the purpose of a pointer in the first place. Pointers are easy once you think about them in a way that makes sense to you. I use my Bucket Analogy to explain pointers.

Think of a bucket sitting somewhere in memory. Buckets come in various sizes, from one that can hold 1 byte of data (e.g., a char or a byte data type), 2 bytes (e.g., int), 4 bytes (e.g., long or float), or almost any size you want. Let's define an integer variable:

int myNum;

Let's further assume that this statement results in a 2-byte bucket that resides at memory address 500. The address where a variable lives in memory is often called its lvalue. Now let's put some data into the bucket:

myNum = 10;

Think of this statement as pouring 2 bytes of data (i.e., 10) into the bucket. The contents of the bucket is often referred to as its rvalue. Most assignment statements take the rvalue on the right side of the equal sign and place it into the rvalue of the variable on the left side of the assignment operator. You could also do this:

int myNum;
int yourNum = 10;

myNum = yourNum;

The last statement takes the rvalue of yourNum (e.g., 10), goes to myNum's lvalue (e.g., 500), and pours those 2 bytes of data into myNum's bucket, thus changing myNum's rvalue to 10.

Now consider this program:

void setup() {
  int myNum;
  int yourNum = 10;
  int *ptr;

  Serial.begin(9600);
  
  //myNum = yourNum;
  ptr = &yourNum;
  myNum = *ptr;
  Serial.print("myNum rvalue = ");
  Serial.println(myNum);
  Serial.print("myNum lvalue = ");
  Serial.println((int) &myNum, HEX);
}

void loop() {
}

Note that we added a pointer variable (*ptr) to the code. In it's definition, the purpose of the int type specifier at the start of its definition tells the compiler the size of the bucket this pointer will be used with; a 2-byte int-sized bucket in this case.

This statement:

  • ptr = &yourNum;*

is where things are different. Rather than the normal ralue-to-rvalue assignment, this statement uses the address-of operrator (&) to tell the compiler NOT to do the normal ralue-to-rvalue assignment, but instead do an lvalue-to-rvalue assignment. In other words, the memory address of yourNum (its lvalue) ends up as the rvalue of the pointer variable ptr. Think about that...

Next, the statement:

myNum = *ptr;

also tells the compiler this is NOT a normal rvalue-to-rvalue assignment. The asterisk says: "use my rvalue as a memory address, go to that memory address and fetch what's there (e.g., grab 2 bytes which form the integer value 10), and take that value and place it into myNum. " This illustrates the process of indirection. That is, use a pointer to indirectly go to a variables lvalue, fetch its contents (i.e., its rvalue), return with it, and shove it into myNum.

The importance of ptr's type specifier is that it tells the compiler how big the bucket is and how many bytes to grab from that memory address. If you had mistakenly used a char pointer to reference an int, the compiler would think the bucket is only 1 byte and would end up grabbing "half an int".

With a function call, normally the compiler makes a copy of value you want to send to the function. If you did this:

  • myFunction(&myNum);*

it would send the lvalue instead of a copy of the rvalue and the function could permanently change myNum's rvalue. Read this several dozen times and it will make sense.