Compiler flaw, probably deliberate, infuriating

The C++ compiler in the Arduino IDE, which I assume is some fork of g++, is a worthy compiler and it supports a lot of modern C++ - lambdas and all sorts of things.

So it's really weird that it's been crippled to reject something that's been part of C from day one.

You cannot pass a pointer to a user defined struct or class to a function. It refuses to recognize the underlying type. Ditto references to structs or the structs themselves. Ditto any user defined types at all, even freaking enums.

This can only be deliberate, and I'm guessing it was done as a lazy hack to prevent inexperienced programmers from passing entire structs to functions, which could rapidly get painful on small processors like arduinos. But in the attempt to Save US All From Ourselves, they blocked all references and pointers to those types as well, and that's unacceptable.

This really makes a mess of some very simple, basic programming techniques, especially involving state machines, which is a lot of what arduinos are for.

I don't need workarounds. I know plenty of ways around this, and they're all poor style or inefficient. If the compiler author wants to turn passing structs into a warning or even disallow it, great. It's not that hard to add to that the compiler. But preventing things as fundamental as passing a ref or pointer to a struct makes simple coding harder and it doesn't actually help anyone.

Fixing this is years overdue.

You are probably doing something wrong. Show us an example

3 Likes

Works for me. You are describing the problem wrong or trying to do something different than what you describe. Give a minimal example.

3 Likes

@gcjr often demonstrates structure usage... find his posts by clicking his profile activity.

2 Likes

I quite often pass pointers to structs, and can't recall ever having a problem.

1 Like

does this demonstrate what you're trying to do

struct Timer {
    const byte    Pin;
    unsigned long msecPeriod;
    unsigned long msecLst;
};

Timer timers [] = {
    { 13, 1000 },
    { 12,  700 },
    { 11,  200 },
    { 10,  500 },
};
const int Ntimer = sizeof (timers) / sizeof(Timer);

unsigned long msec;

// -----------------------------------------------------------------------------
void
timerChk (
    Timer *t )
{
    if (msec - t->msecLst >= t->msecPeriod)  {
        t->msecLst = msec;
        digitalWrite (t->Pin, ! digitalRead (t->Pin));
    }
}

// -----------------------------------------------------------------------------
void loop()
{
    msec = millis ();
    Timer *t = timers;
    for (unsigned n = 0; n < Ntimer; n++, t++)
        timerChk (t);
}

// -----------------------------------------------------------------------------
void setup()
{
    Serial.begin(115200);

    Timer *t = timers;
    for (unsigned n = 0; n < Ntimer; n++, t++)
        pinMode (t->Pin, OUTPUT);
}

1 Like

This is most likely the cause of your problem, I have run into the situation a few times and inserting a function prototype at an appropriate location fixed it.

2 Likes

Oh for pity's sake. Is there a way to turn off the automatic generation of prototypes? I'm an experienced C++ programmer and I define (or declare) my functions before they are used, so I absolutely don't need the IDE adding incorrect crap to my already well formed code. If it's going to try to dumb down C++ so people don't have to create forward references, it should at least figure out when they are not needed. Barring that there need to be an Off switch.

That's really annoying.

Generate them yourself, or use a professional IDE. Or use one of the fixes already presented.

The Arduino IDE is free software, intended for teaching and learning, and making life a little less complicated for beginners.

The phrase "probably deliberate" in the post title is a ridiculous accusation and does not engender sympathy.

2 Likes

what's wrong with the code a posted? isn't you're similarly structured?

can you post your code

If you provide a function prototype, the IDE will not attempt to generate a prototype for the function. Not sure if the automatic prototype generation can be entirely disabled.

You can also provide your own main() function, and do away with the necessity of having setup() and loop().

Actually, no. This IS deliberate behavior on the part of the IDE, and it's not making things better. It's teaching people bad C++ - in C++, you either define or declare everything before use. The IDE is trying to make that important aspect of the language go away in the name of "simplification" - and then hassling people who know the actual rules, by helpfully doing something wrong.

Imagine someone starting out coding with an Arduino and then trying to move C++ professionally, and getting confused about all this talk of forward references. That's a disservice.

I've been using C++ since the cfront days, so I'm not a typical arduino hobbyist. If there's a better IDE out there, I'd be willing to pay for it.

is it any better if you put that code in a .cpp file and call it from the .ino?

Do keep digging that pit you are in! Bye.

+1
I think that sums it up.

I haven't gone looking, but this thread begs the question - is there a 'graduate course' for our learners, that takes them from the handholding(childhood) of the IDE to a stand-alone 'grown up'(perhaps, someone should have used a slightly different, less negative, phrasing...) world?
Just asking, as it would seem some here believe there are two worlds - Arduino 'baby', and 'C++' adult, which would seem to suggest there's room for a 'training wheels' stage.

What I don't understand is that if you are defining the functions before they are being used then why do you have a problem ?

Have you provided an example of a sketch that illustrates your problem ?

@UKHeliBob

You can try the example in Incorrect placement of auto-generated prototypes gives misleading error messages · Issue #362 · arduino/arduino-builder · GitHub

interesting report raised in Nov 2020

comment:

We'll investigate soon and report back

reported as 'preprocessing type: imperfection' end of sept 2021

and mid 2023 there is no change (still fails in IDE v2)

I guess we can all live with an imperfect world

side note: reordering it a bit solves the issue

// Arduino IDE 1.8.13

enum class StateA { one, two, three } ;
enum class StateB { one, two, three } ;

StateA stateA ;
StateB stateB ;

void setStateA( StateA newState ) { stateA = newState ;}
void setStateB( StateB newState ) {stateB = newState ;}

void setup() {
  setStateA( StateA::one ) ;
  setStateB( StateB::one ) ;
}

void loop() {}

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