Home > database >  Initializing a Struct passed by refence with a Macro
Initializing a Struct passed by refence with a Macro

Time:05-24

In the past, I have used a macro for initializing an Struct with this scheme:

node.h

typedef struct Node_TypeDef
{
    uint16_t netId;
    const uint8_t UID[6];
}Node_TypeDef

#define NODE_INIT                                       \
{                                                         \
    0x0002,                                 /*NetID*/     \
    {0x03, 0x44, 0x03, 0x00, 0xA0, 0x08},   /*UID*/       \
}

main.c

#include "node.h"
 
int main(void) {

    Node_TypeDef node = NODE_INIT;
    

/*More Code*/

}

Now I want to put the initialization code in a function that receives a pointer to the struct, then populates it depending on the second parameter using the macro directives. Something like this:

node.h

typedef struct Node_TypeDef
{
    uint16_t netId;
    const uint8_t UID[6];
}Node_TypeDef

#define NODE_INIT_1                                      \
{                                                         \
    0x0001,                                 /*NetID*/     \
    {0x03, 0x44, 0x03, 0x00, 0xA0, 0x08}    /*UID*/       \
}

#define NODE_INIT_2                                       \
{                                                         \
    0x0001,                                 /*NetID*/     \
    {0x03, 0x44, 0x03, 0x00, 0xA0, 0x08}    /*UID*/       \
}

.
.
.
.

#define NODE_INIT_N                                          \
{                                                            \
    0x0001,                                 /*NetID*/        \
    {0x03, 0x75, 0x03, 0x00, 0xD0, 0x0A}    /*UID*/          \
}

void initNode (Node_TypeDef *node, uint8_t mode);

node.c

#include node.h

Node_TypeDef ptrNode;
 
void initNode (Node_TypeDef *node, uint8_t mode)
{
    switch (mode) {
    case 1:
        *node = NODE_INIT_1; 
        break;
    case 2:
        *node = NODE_INIT_2;
        break;
     .
     .
     .
    default:
        break;
    }
    ptrNode = node; 
}

main.c

#include "node.h"
 
int main(void) {

    Node_TypeDef node;
    initNode (&node,2);
    

/*More Code*/

}

Nevertheless, as a macro, it's not a variable. It is replaced in compilation time; the deference operator can not just assign the value. Furthermore, as is a struct, I should use a memcpy() for assigning it, but I need the memory address where this constant was placed.

In Summary:

How can I assign a value to my struct that was passed by reference to a constant value defined in a macro?

I appreciate any help with this.

CodePudding user response:

For this, you need compound literal:

#define NODE_INIT           \                                   
    ((struct Node_TypeDef){ \                                                        
    0x0002,  /*NetID*/      \
    {0x03, 0x44, 0x03, 0x00, 0xA0, 0x08}, /*UID*/ })

After that, this should work:

*node = NODE_INIT; 

CodePudding user response:

Only the (type) information was missing. Kudos to @hyde for the link: compound literal

#include <stdint.h>
#include <stdio.h>

typedef struct Node_TypeDef
{
    uint16_t netId;
    uint8_t UID[6];
} Node_TypeDef;

#define NODE_INIT_1 (Node_TypeDef)                        \
{                                                         \
    0x0001,                                 /*NetID*/     \
    {0x03, 0x44, 0x03, 0x00, 0xA0, 0x08}    /*UID*/       \
}
void initNode (Node_TypeDef *node, uint8_t mode);

Node_TypeDef *ptrNode;
 
void initNode (Node_TypeDef *node, uint8_t mode)
{
    switch (mode) {
    case 1:
        *node = NODE_INIT_1; 
        break;
    default:
        break;
    }
    ptrNode = node; 
}
 
int main(void) {

    Node_TypeDef node;
    initNode (&node,1);
    printf("netId: %d\n", node.netId);

/*More Code*/
    return 0;
}
netId: 1

Test at online environment

  • Related