How to modify a global variable with a macro?

Is there a way to define a macro in a header file using a class structure such that it would be a simple matter of calling the name of the class along with the macro to affect change on that global variable?

Here is a simplified example of what I'm trying to do ... but obviously this doesn't work:

#ifndef Library_h
#define Library_h

bool itemEnabled;

class Library {

#define DISABLE_ITEM itemEnabled = false

public:
    Library(unsigned long time, char color);

private:
    unsigned long timeValue = 0;
    char mainColor;

};
#endif

And I'd like to be able to call the macro in a sketch like this - or in some similar simple fassion:

#include <library.h>

Library::DISABLE_ITEM;

void setup() {

}

void loop() {

}

Is there any way to do this?

Mike

if it's a global variable, just change its value in the setup ... not sure what it has to do with the library or class

OK, so when I try that using this sketch:

#include <library.h>

itemEnabled = false;

void setup() {

}

void loop() {

}

The compiler throws an error:

delete:10:1: error: 'itemEnabled' does not name a type
 itemEnabled = false;
 ^~~~~~~~~~~
exit status 1
'itemEnabled' does not name a type

A variable can only be modified in functions, do that in setup for example (and if it’s defined as a global in another file, it needs to be declared extern so that the main sketch would know about it)

So that's kind of why I wanted to be able to set it with a macro ... in terms of simplicity for the user of the library ... instead of having them do this:

itemEnabled = false;

Which has no reference to this library, I would much prefer to have them do this:

Library::DISABLE_ITEM

or some similar way where the library is referenced and they know that they are affecting change on a variable that is specific to Library.

You can only give a default value to a variable where you allocate the memory (define the variable). So if later you want to change that value then this is code that has to be executed and thus it needs to be in a function.

You could write ClassName::variable = false; if you want (for a public static attribute) or call a method on your library that will modify the variable.

The fewer preprocessor macros you use the better. Make itemEnabled a private member of your library class and supply a public setter function. Also, if the user ever needs to know the variable's value, provide a public getter function.

1 Like

In the context of a class, the rough equivalent of a 'global variable' is a 'class static variable'. It's a variable shared with all instances of the class. A 'class static function' can be used to modify the 'class static variable'.

#ifndef Library_h
#define Library_h

#define DISABLE_ITEM Library::disable()

class Library
{
  public:
    Library(unsigned long time, char color);
    static void disable()
    {
      itemEnabled = false;
    }

  private:
    static bool itemEnabled;
    unsigned long timeValue = 0;
    char mainColor;
};

bool Library::itemEnabled = true;
#endif

// #include <library.h>



void setup()
{
  DISABLE_ITEM;
}

void loop()
{
}

Note: If your library has a .cpp file as well as the .h file you should put the definition of the class static variable there:
bool Library::itemEnabled = true;
If that line is in the .h file you can't use the .h file in more than one .cpp/.ino file or you'll get multiple definitions of 'itemEnabled'.

But why would you do this?
It is immediately clear that Library::disable(); is a function call that disables something in Library.
DISABLE_ITEM; on the other hand is not a standard C++ statement or expression, it is impossible to tell what it is or what it's doing without diving into the library source code to look at its definition.

first, this is clear, because you can't assign a new value outside setup() or loop
this compiles:

#include "library.h"

//itemEnabled = false;  // the variable can not get a new value here

void setup() {
  itemEnabled = false;  // the variable can be set here
}

void loop() {
  itemEnabled = false;  // the variable can be set here
}

if you have global variable in your .h and you want to let the user modify the variable, you could introduce simple functions for that like a
"switchOn()" and "switchOff()

A makro would be my last option in 2021.

But does it really need to be a global?

as johnwasser and J-M-L already mentioned, if you want the context to your class, why not a static member within your class and call a method with any object of that class?

btw: as you mentioned you want to write a library (for others): I highly recommend this article
Sparkfun: How to Write a Great Arduino Library
first they inlcude 2 important links to Arduino articles you should read, and then they share their expirience of how to write a library with do's and don'ts

I wouldn't, but that is what the OP wanted.

And this is EXACTLY the situation I am in. I need the variable to be viewable in whatever value it has assigned to it - to all instances of the class. However, the library is indeed composed of a header file and a .cpp code file.

So what do I do in my situation where I need the variable to exist outside of any instantiations of the library class, but also modifiable by the user's code? What this is ... it's a simple non-blocking timer library that has a feature where it keeps an array of the class every time it is instantiated so that the user can issue a single reset command and reset all instantiated timers at once. But I want to be able to offer the ability to disable that feature in the interest of saving memory if someone is in that situation where every byte counts.

bool itemEnabled = false;

The library has been written and published for some time now. This post was over something I've been trying to implement into the library. Specifically, the ability to disable a function that exists outside of the class definitions.

I was able to do what I wanted to do finally, by using an enum that is declared outside of the class structure and the using a variable inside the class, and then use Maco's that get passed into any of the class definitions.

If you want any code to be able to modify the variable at any time, move it to the public: part of the class declaration. Then any code that knows the name can change the value. The macro can then be:

#define DISABLE_ITEM (Library::itemEnabled = false)

I prefer to keep a class's internal state variables private. Then, supply public setter and getter functions. That way I control what the user is allowed to do.

As pointed out in this post and OP's other similar post, using preprocessor macros should be avoided if there's a better solution. In this case there is.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.