LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

a bug with structure containing bit fields ?

Solved!
Go to solution

using CVI 8.5. i was trying to define a structure containing bit fields. although the structure compiles properly, i do encounter a strange behavior when accessing the individual fields, while the global structure value seems ok. here is the structure:

 

typedef struct
{
    union
    {
        struct
        {
            unsigned int flag1  : 1;
            unsigned int dummy  : 3;
            unsigned int flag2  : 4;
            unsigned int flag3  : 4;
            unsigned int dummy2 : 4;
        };
        unsigned short all;
    } flags;
} flagset;

 

when setting the "all" member to a value made so that one or more flags, but not all, are false, i do still read individual flags as true, until all flags are set to false.

did i miss something ? is this definition really legal ?

 

you will find attached a file demonstrating the problem.

0 Kudos
Message 1 of 5
(3,636 Views)

It does appear to be a bug, but it's a bug with printf. If you look at the variables window while debugging your program or examine any control flow in your program based on these flag values, you'll see that everything is as it should be. What I'm seeing with printf is that it reuses the first evaluated bitfield value (arguments evaluated from right to left) for any subsequent bitfield values. So, when you're printing out field1, field2, and field3, it will print the value of field3 for all three. If you reverse the order of the arguments to printf so that field1 is last, you'll see that all the fields print out as 0 as soon as you've cleared field1.

 

We'll try to fix this for a future version. Thanks for catching it.

 

Mert A.

National Instruments

0 Kudos
Message 2 of 5
(3,626 Views)
Also, I had wanted to mention one more thing as a sidenote: you could make your flagset structure 2-bytes long (as it seems you intended) by declaring the bitfield members as unsigned short rather than unsigned int. Because you've declared them as unsigned int, your inner struct is actually the size of a 4-byte integer, and therefore, so is your union and outer struct.
0 Kudos
Message 3 of 5
(3,620 Views)

you are right: the original structure was 16 bit wide. the unsigned int declaration is the result of a test.

 

there is still one point i need to clarify. i originally noticed this when using the ternary operator (cond ? true : false). so i augmented my test to watch the output with a ternary operator.

when the ternary is used as an argument to printf, the test fails. when the ternary is outside of the printf call, the test passes. i also made the same test with a function other than printf, and the behavior is always correct.

 

that's where i do not understand: if the ternary is an argument to printf, it should be evaluated _before_ calling printf, the result being pushed on the stack, thus the result should be identical in the 2 cases, and the test should pass.

0 Kudos
Message 4 of 5
(3,594 Views)
Solution
Accepted by dummy_decoy

The same issue is at play with or without the ternary operator. It turned out the problem was not specifically with printf, but rather a compiler bug related to evaluation of members of anonymous inner structs. If multiple anonymous inner struct members are evaluated before the compiler actually does anything with the result -- which is the case when passing arguments to a function -- then they will all evaluate to the value of the one that was evaluated last.

 

Mert A.

National Instruments

0 Kudos
Message 5 of 5
(3,577 Views)