1

I'm trying to pass variable addresses to functions/methods within a custom library that should change the values at the specified addresses. However, I think I'm missing something as it's taking me ages to tweak things just to get it to compile, let alone gather some useful information from it.

Note: I've not tested the code as I'm focused on understanding (1.) through to (5.) and is just a quick example of the current pipeline:

Main.ino

#include <customLibrary.h>

CustomLibrary cLib();

byte someByte[6];
unsigned int theAddress;

setup(){};

loop(){

    // (1.)
    theAddress = &someByte; // normally need this here, or before setup(), for it to work.

    cLib.setValues(theAddress); 

    // because:
    // cLib.setValues(&someByte);  
    // doesn't seem to work
};

customLibrary.h

#ifndef CustomLib
#define CustomLib
#if(ARDUINO > 100)
    #include "Arduino.h"
#else
    #include "WProgram.h"
#endif

class CustomLibrary {
    public:
        CustomLibrary();
        void setValues(unsigned int theAddress); // (2.)
    private:
};
#endif   

customLibrary.cpp

#include <customLibrary.h>

CustomLibrary::CustomLibrary(){
};

void CustomLibrary::setValues(unsigned int theAddress){ // (3.)

    byte _someNewValues[6] = {a,b,c,d,e,f};

    // Assign the variable from _someNewValues[_x] to (theAddress + _x) 
    int _x = 0;
    for(unsigned int i = theAddress;i < (theAddress + 6);i++){ // (4.)
        // (5.)
        _x++;
    };

};

(1.) - Feels like it should be simpler.

(2-3-4-5.) - I have left out any "*" and "&" hoping that someone can provide the preferred way of doing this, or provide a better solution as it's taking far too long to get this working with everything else leading me to think I'm missing something basic.

There are some excellent tutorials out there which I have been following with great success, but, only when all the pointers are within the same file. Once I try and use them in a library it's a constant headache at the moment and I don't understand it enough to know what's wrong.

Need to go before I can proof-read and check it, but I think it's all there. I'll be back later/tomorrow if there's anything that needs clearing up.

Edit: I didn't know who to mark for the answer as both @dannyf and @KIIV answered perfectly. I considered marking the answer based on the time it was posted, but decided instead to let @dannyf have it as his reputation was only 1.

Thank you both! Much appreciated!

2 Answers 2

1

somebyte itself is a pointer. so "&somebyte" doesn't make sense.

instead, use "&somebyte[0]" (or "&somebyte[5]" if you want an offset), or "somebyte" (or "somebyte + 5" if you want an offset).

arrays are actually pointers.

3
  • Excellent, I had heard that arrays were pointers, just never came across them being an issue explicitly using them as pointers. I missed a second variable, byte anotherByte;, not an array, however, it has an identical pipeline to follow as _someByte[] does. In that case, what would you do for (2-3-4.)? *theAddress for (2-3-4.)? and at (5.) have something similar to *theAddress = anotherSomeValue; . Apologies, I'm just making 100% sure I've got this because trying to debug it through the error window which is abstract at best when I'm not 100% about something. Thanks!
    – user32744
    Dec 2, 2017 at 10:14
  • if you wish to change the value stored at the address pointed to by theAddress, use "*theAddress = someValue;" But the function should indicate that theAddress is a pointer of a particular data type.
    – dannyf
    Dec 2, 2017 at 13:11
  • 1
    To make this a bit more explicit: A reference to an array is a pointer to the array's first member. That is what actually gets passed when you "pass an array" to a function, or a function returns an array.
    – JRobert
    Dec 10, 2017 at 16:22
0

I'm not sure how it could ever work for you in both variants. There is simple example how to work with arrays:

class CustomLibrary {
    public:
        CustomLibrary() {;}

        void setValues(byte * address);

        template <class T, int SIZE>
        void setValuesTemplate(T(&bytes)[SIZE])
        {
          for (int8_t i=0; i<SIZE; ++i)
          {
            ++bytes[i]; // just increment the value
          };
        }
 };

void CustomLibrary::setValues(byte * address){
    byte somethingNew[] = {'a','b','c','d','e','f'};

    for (int8_t i=0; i<6; ++i)
    {
      address[i] = somethingNew[i];
    }

};


CustomLibrary lib;

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

void loop(){
  byte someByte[6] = {'z','y','x','w','v','u'};

  Serial.println("Values before:");
  for (byte b : someByte) Serial.print(b, HEX); 
  Serial.println();

  lib.setValuesTemplate(someByte);

  Serial.println("Values after templated method:");
  for (byte b : someByte) Serial.print(b, HEX); 
  Serial.println();

  lib.setValues(someByte);

  Serial.println("Values after method:");
  for (byte b : someByte) Serial.print(b, HEX); 
  Serial.println();

  delay(5000);
};

It's in single .ino file for testing purposes. If you want to use templates, you have to place template method definition into the header file (it doesn't have to be inside class definition, it just have to be in header file).

Range based for loop was introduced by C++11 standard (suported by Arduino IDE for a while - since about version 1.6.5?). It's realy handy on static arrays (like int arr[] = {......}), so you don't have to care about it size. But it's basically everything it can do on avr-g++, as there are no containers, no iterators and so on.

Templates are quite huge topic on C++, in this case it's working with T as array element type and SIZE as its size (it won't work on pointers, it only works on static arrays).

I could've use range based for loop in int too:

    template <class T, int SIZE>
    void setValuesTemplate(T(&arr)[SIZE])
    {
      for (T& item : arr) // it must be a reference type, if you don't want to change local value only
      {
        ++item; // just increment the value
      };
    }

And I didn't even needed that class T part. If you need byte array only:

    template <int SIZE>
    void setValuesTemplate(byte(&arr)[SIZE])
    {
      for (byte& item : arr) 
      {
        ++item;
      };
    }

But there is a downside for using templates -> there will one instance of that method for each type/size. But it's possible to use it as a "proxy" and pass it to function that expects just pointer and the size.

2
  • Thanks for the help! That's introduced two new things, which is great as I've not used them before. template <class,size> and for(byte b : someByte)! As a guess: for(x : y) /* something */ ; is shorthand, like (x) ? x : y;?
    – user32744
    Dec 2, 2017 at 10:21
  • 1
    @Timeless I've added more detailed description into the answer.
    – KIIV
    Dec 2, 2017 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.