[solved] Filling an array using pointer

Hello everyone.

I'm once again lost with the whole passing arrays as pointer so my program does not forget that the array exists outside the function.

void testAfunc(int* x,int* arr, int size) {

  int temp[size];
  for(int i=0;i<5;i++) {
    Serial.print("arr["); Serial.print(i); Serial.print("]"); Serial.println(arr[i]);
    x[i] = arr[i];
  }
}

void loop() {
  int arr[] = { 3, 5, 6, 7, 9 };
  int* x;

  testAfunc(x,arr,5);
  Serial.print("TestAFunc: ");
  for(int i=0;i<5;i++) {
    Serial.print(x[i]); Serial.print(" ");
  } Serial.println(" ");

  Serial.println("XXXXXXXXXXXXXXXXXXXXXXXX");

   delay(7500);
}

Later on I will have my own datatype which holds different values (name, size, datarray,...). But the array values I entered "dissapear". It looks more like the wrong address is called (completly nonsense values).

Datastorage DATA;


void myFancyFunction(DATA) {

 // do some stuff with DATA

}

void loop() {

 myFancyFunction(DATA);


 // still use all the information held by DATA


}

My datastorage looks like this

class Datastorage {

 Datastorage(char*);

 void setResults(int*);
 int* getResults();

 int SIZE = -1;
 int* RESULTS;
 char* NAME;

}

Thanks for the help

It would be a lot easier to help if you posted a complete code (that actually compiles) all in one Code Tag window.

Your array is associated ONLY with that function. When the function is entered, the address of the array is established. When the function is exited, the address disappears and a new address is established when the function is entered next time.

Define the array at the beginning of the program so it is fixed in location.

Paul

Sorry. Here it is

#include <Arduino.h>

void setup() {
    Serial.begin(9600);
}


void testAfunc(int* x,int* arr, int size) {

  int temp[size];
  for(int i=0;i<size;i++) {
    //Serial.print("arr["); Serial.print(i); Serial.print("]"); Serial.println(arr[i]);
    temp[i] = arr[i];
  }

  x = temp;
}

void loop() {
  
  int arr[] = {3, 5, 6, 7, 9 };
  int* x;

  testAfunc(x,arr,5);
  // x = arr;
  Serial.print("TestAFunc: ");
  for(int i=0;i<5;i++) {
    Serial.print(x[i]); Serial.print(" ");
  } Serial.println(" ");

  Serial.println("XXXXXXXXXXXXXXXXXXXXXXXX");

   delay(7500);
}

Time to read this:
Scope
https://forum.arduino.cc/index.php?topic=383064.0

Paul_KD7HB:
Your array is associated ONLY with that function. When the function is entered, the address of the array is established. When the function is exited, the address disappears and a new address is established when the function is entered next time.

Similarly, the statement:

x = temp;

doesn't do what you think it does either. It only modifies the local copy of the passed argument (on the stack). It doesn't change the value of 'x' in the calling function (loop).

I tried the suggestion of Paul and defined the pointer outside the functions. Same results.

Why should the function care where the array is defined? The address is given at the moment its created. When I pass it as pointer to any function should the address not be the same?

Are you trying to reinvent memcpy?

If it was that easy...

I would like to have my own datatype DATASTORAGE which holds all kind of information of a chip I'm working on. This information (int* RESULTS) changes when the chip is called.
I want to write data into the DATASTORAGE and pass the variable to some functions.

The data inside the DATASTORAGE is correct (printing inside the seter Method). When the data is called upon later on it looks like the wrong address (SIZE and NAME are still correct).

I somehow "solved" it.

The storage is now conveniently named Arrayreturner.

The header file 'Arrayreturner.h'

#ifndef ARRAYRETURNER_H
#define ARRAYRETURNER_H

#include <Arduino.h>
#include <Wire.h>

class Arrayreturner {
public:

  Arrayreturner();

  void setResults(int* res, int size);
  int* getResults();
  void show();


  int* results;
  int rsize = -1;
  char* name;
};

#endif

The function file 'Arrayreturner.pp'

#include "Arrayreturner.h"

Arrayreturner::Arrayreturner() { }

void Arrayreturner::setResults(int* res, int size) {
  rsize = size;

  results = res;
}

int* Arrayreturner::getResults() {
  return results;
}

void Arrayreturner::show() {
  Serial.print("SIZE: "); Serial.println(rsize);
  Serial.print("SHOW: ");
  for(int i=0;i<5;i++) {
    Serial.print(results[i]); Serial.print(" ");
  } Serial.println(" ");
}

The main program

#include <Arduino.h>
#include "Arrayreturner.h"

void setup() {
    Serial.begin(9600);
}

Arrayreturner testfunc(int* arr, int size) {

  Arrayreturner aret;  

  aret.setResults(arr, 5);

  aret.show();

  // Serial.print("testfunc: ");
  // for(int i=0;i<5;i++) {
  //   Serial.print(aret.results[i]); Serial.print(" ");
  // } Serial.println(" ");
  return aret;
}

void loop() {

  int arr[] = {3, 5, 6, 7, 9 };
  Arrayreturner ar;
  ar = testfunc(arr, 5);

  int* res = ar.getResults();
  Serial.print("res: ");
  for(int i=0;i<5;i++) {
    Serial.print(res[i]); Serial.print(" ");
  } Serial.println(" ");

  Serial.println("--------------");

  delay(7500);
}

I have now my custom datatype, can fill it with data from another function (my chip) and use it outside this function (in other functions or pass it along).

Now that I see it, it kind of makes sense (until it stops behaving like I want it to)

Is this the right (elegant) way to do what I'm trying to do?

v3xX:
Is this the right (elegant) way to do what I'm trying to do?

"Convoluted" is the term I'd use.

You didn't elaborate on the details of your "chip" DATASTORAGE, but it seems reasonable to use a 'struct' for it. I would keep that struct private within the class and not pass pointers to it around.

This seems a lot more straight forward to me:

struct chipInfo {
  uint8_t parameter1;
  uint8_t parameter2;
  uint16_t parameter3;
};

class Chip {
  private:
    chipInfo privateInfo;
  public:
    void setInfo(chipInfo *);
    void getInfo(chipInfo *);
};

void Chip::setInfo(chipInfo *incoming) {
  memcpy((void *)(&privateInfo), (void *)incoming, sizeof(chipInfo));
}

void  Chip::getInfo(chipInfo *outgoing) {
  memcpy((void *)(outgoing), (void *)(&privateInfo), sizeof(chipInfo));
}


void setup() {
  Chip myChip;
  chipInfo newInfo = {1, 2, 500};
  chipInfo retrievedInfo;

  Serial.begin(115200);
  delay(2000);

  myChip.setInfo(&newInfo);
  myChip.getInfo(&retrievedInfo);
  Serial.println(retrievedInfo.parameter1);
  Serial.println(retrievedInfo.parameter2);
  Serial.println(retrievedInfo.parameter3);
}

void loop() {
}

@gfvalvo: I played around with your suggestion and used a 'Struct' definition across multiple files. Also I modified the Chip-Class and the other classes which use the chipdata (now as Struct). I also tried to streamline the passing of the arguments.

I think the whole Pointer and addressing business is clear for now, until the next seemingly easy problem arrives.
Thanks for the help.