Passing enum variable to a function

I am trying to pass an enum variable to a subroutine. The code is shown below.
I thought that the declaration
enum I2C1_MESSAGE_STATUS humid_status;
would have alocated the approriate storage, but based upon the 1st failure (shown below) perhaps not.
Looking more carefully at the subroutine declaration it wants a pointer to the message status.
However trying case 2 below I still get and error claiming that "a pointer was expected but the argument is of type pointer"??!!
Probably I do not quite understand how enums are stored.

Can someone clairfy for me the proper way to pass the argument?
Thanks!
Fritz
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

void I2C1_MasterWrite( uint8_t *pdata, uint8_t length, uint16_t address, I2C1_MESSAGE_STATUS *pstatus);

typedef enum
{
I2C1_MESSAGE_FAIL,
I2C1_MESSAGE_PENDING,
} I2C1_MESSAGE_STATUS;

//1st failure
main(void) {
...

enum I2C1_MESSAGE_STATUS humid_status;
I2C1_MasterWrite ( pdata1, 1, 0x0040, humid_status);
....

main.c:63:6: error: 'humid_status' has an incomplete type


// 2nd failure--USING ADDRESS POINTER
main(void) {
...

enum I2C1_MESSAGE_STATUS humid_status;
I2C1_MasterWrite ( pdata1, 1, 0x0040, &humid_status);
....

main.c:63:6: warning: passing argument 4 of 'I2C1_MasterWrite' from incompatible pointer type
mcc_generated_files/i2c1.h:274:6: note: expected 'enum I2C1_MESSAGE_STATUS *' but argument is of type 'enum I2C1_MESSAGE_STATUS *'
typedef is not useful -- it smacks of C code and older styles.
just say:
enum I2C1_MESSAGE_STATUS
{
I2C1_MESSAGE_FAIL,
I2C1_MESSAGE_PENDING
};

void foo(int x, I2C1_MESSAGE_STATUS mc)
...
foo(3, I2C1_MESSAGE_FAIL);

you have an extra comma in your enum.

I am not sure you can take the address of enum members?
I tried it and I get:
x3.cpp:17:7: error: lvalue required as unary '&' operand
foo(&a);
^
They are just constants, its like say &5 which is nonsense. Enums are just integers, and pointers are just integers: its no more efficient to use pointers here, actually its less efficient... just pass copies. You can pass a pointer to the enum type, but then you need something to point to:

I tried this approach and it does work:
void foo(int x, I2C1_MESSAGE_STATUS *mc)
...
I2C1_MESSAGE_STATUS useful = I2C1_MESSAGE_FAIL;
foo(3, &useful);

a bit of playing with it, I could not get references nor pointers to the internal enum constants, but I could do both with a local variable of the enum type.

this makes sense. The compiler tries to optimize enums. Think of it this way: enums are an alias for a constant integer. The compiler does not need a name, it can work fine using 1, 7, and 11 for example right in the assembly code. The names are for the human, instead of
array[11]
you have
array[usefulname];
and so on. but the compiler down at the machine code generation still generates array[11]. So they are not 'stored' so much as 'looked up and inserted upon demand'.
There is a tool called the enum class that can do a bit more things. I have yet to find a use for it, but it may be able to do this, I do not know.
Last edited on
closed account (z05DSL3A)
fsonnichsen, I'm going to assume you are writing C and you probably just need to move your definition of the enum, something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef enum
{
        I2C1_MESSAGE_FAIL,
        I2C1_MESSAGE_PENDING,
} I2C1_MESSAGE_STATUS;


void I2C1_MasterWrite( I2C1_MESSAGE_STATUS *pstatus)
{

}

int main(void)
{
        I2C1_MESSAGE_STATUS status;
        I2C1_MasterWrite(&status);
}
Thanks for the reply.
I should have been more clear but the preliminary code defining the enum and the function declaration are immutable as they are generated by the Microchip MCC facility and I cannot change them. Thus I do not have control over the typedef. (The extra comma was a typo by me truncating it for clarity but not in their code).

The *pstatus (as humid-status) is passed TOO me from the subroutine after it runs.
Thus I need a receiver for this data.

I thought my statement:
num I2C1_MESSAGE_STATUS humid_status;
would allocate the storage necessary to hold the returned data. But apparently not.

So whether I use "humid-status" or its address I get an error.

Thanks
Fritz
Sorry for my somewhat short reply above--for some reason my browser omitted half of jonnin's reply and all of the next.
At any rate, per Grey Wolf, I omitted the "enum" from my declaration of "humid-status" and it compiles. I had tried this earlier but not put the "&" on the recall.
All of this is a bit strange to me as I do not really know what is going on under the covers-I wish the documentation would expand things into assembly so we could see what actually happens! Jonnin alludes to this. I had consulted K&R on this and the didn't shed much light. "enum" was something they did not have in their first edition.

All told when i write all the code myself I do not use enum for aforesaid reasons. I never really found it all that useful but then my code is very 1980s!
I will pop my new code into the microprocessor soon and hope it works.

You guys spent a lot of time on this--I really appreciated it
Fritz
you can compile your code to dump an assembly file with the c++ code that relates to it in the comments. Should be a setting/flag on your compiler. Its not very useful if you don't know asm, but you can see what its doing. A smaller sample program is better, even just a few lines. Different compilers will generate slightly different assembly for the same c++ for the same chip. Its not set in stone, all that is required is that it works.

enums are useful when you have related integer constants.
here, check this out:
enum days {monday, tuesday, wendsday, thursday, friday, saturday, sunday};
not very interesting, is it?
now check this out:
enum days {monday, tuesday, wendsday, thursday, friday, weekday, weekend, saturday, sunday};
...
blah blah if(today < weekday) ;//its a weekday!
blah blah ... if(today > weekend); // its a weekend!
you can organize groups of constants to have pretty logic, instead of saying if day < saturday (what does this mean, got to go look at the enum to see what the author was doing)
this is kind of a rushed dumb example but you can split stuff up, name array/vector locations so you can treat a simple vector like a struct or whatever without having to do anything special.
one more handy example:
enum { one, two, three, max};
int storage[max]{};
storage[two] = value;
...
oh no, its years later and I need a fourth location, but I need it before three, what to do?!
no problem:
change it to
enum { one, two, twoptfive, three, max};
and recompile and everything that worked before still works, and you have another location now in the ordering you wanted.

There are a LOT of improvements since 1980. Projects are bigger and the language is better suited to help you handle giant projects and do things more efficiently, with less rewriting of basic common things and more focus on the meat of your work. The downside is the language is gigantic now, C not as much as C++.
I didn't realize it was C, glad you got it working.
Last edited on
closed account (z05DSL3A)
fsonnichsen wrote:
All of this is a bit strange to me as I do not really know what is going on under the covers-I wish the documentation would expand things into assembly so we could see what actually happens!

Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go (and many more) code. [ https://godbolt.org/ ] It is a good tool for investigating what is going on.
Topic archived. No new replies allowed.