1

I'm trying to use structs with Arduino but cannot pass a struct pointer with a function call. Everything works fine when adding a main function and compiling for my computer with gcc but with the Arduino IDE I get errors.

The code I tried was:

typedef union
{
    struct
    {
        unsigned unit   :2;
        unsigned channel:2;
        unsigned status :1;
        unsigned group  :1;
        unsigned remote :26;
    };
    unsigned long data;
} Signal;

Signal signal;

void testPassingStruct(Signal *variable)
{
    variable->status = 1;
}

void setup()
{
    signal.status = 1;
    testPassingStruct(&signal);
}

void loop()
{
}

And the errors was:

structtest:2: error: variable or field ‘testPassingStruct’ declared void
structtest:2: error: ‘Signal’ was not declared in this scope
structtest:2: error: ‘variable’ was not declared in this scope

2 Answers 2

3

You have several unnamed items. This happens with typedefs. You could try,

union sig_union
{
    struct
    {
        unsigned unit   :2;
        unsigned channel:2;
        unsigned status :1;
        unsigned group  :1;
        unsigned remote :26;
    } d;                       /* Note the name here. */
    unsigned long data;
} signal;
typedef union sig_union Signal;

Then in your code you need,

void testPassingStruct(Signal *variable)
{
    variable->d.status = 1;
}

You can also use defines for masks and bit fields. Often it makes control of what bit is where clearer and the compiler will generate similar code in both cases. For instance,

#define SIG_UNIT(d)    (d&0x3)
#define SIG_CHANNEL(d) (d&0xc>>2)
#define SIG_STATUS(d)  (d&0x10)
/* etc. */

Especially with system programming where the bits matter, this is better as I don't believe that the 'C' bit fields specify how they are placed. Most of all, I am sure it will compile.

Sign up to request clarification or add additional context in comments.

3 Comments

The ATMega/AVR may have troubles with your nested struct/union. It has limited 8 bit registers. I think the defines will definitely work although there is a little bit more boiler-plate code.
It's 4 bytes, which is 2 registers. Hardly a challenge for anything more powerful than a ATtiny10.
@IgnacioVazquez-Abrams Yes, but for most CPUs it would only be a single register; I am just saying that it is not unfathomable that the compiler may have issue with this; I think it is the other issues I noted. Especially, the error message would have been different if it was an register allocation.
3

It is basically the union and the lack of a the name for the structure member (I've called it parts in the code below). Try this

union Signal
{
    struct
    {
        unsigned unit   :2;
        unsigned channel:2;
        unsigned status :1;
        unsigned group  :1;
        unsigned remote :26;
    } parts;
    unsigned long data;
};

union Signal signal;

void testPassingStruct(union Signal *variable)
{
    variable->parts.status = 1;
}

void setup()
{
    signal.parts.status = 1;
    testPassingStruct(&signal);
}

void loop()
{
}

2 Comments

Will I then be able to use signal.data to iterate over all 5 parts that makes up the 32 bits? I need that to send the signal via a 433Mhz transmitter.
Yes - in fact trying it would have been faster than asking.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.