-1

I'm trying to define a structure as a typedef in a header file and use it in many sources. I found a similar answer in here but I'm not sure if a typedef can be defined as extern. Also msg_encoded should have a default value.

// lib.h

#ifndef lib_h
#define lib_h

struct msg_encoded_s
{
    uint8_t msg[10];
    int length;
} msg_encoded_default = {{0}, 0};

typedef struct msg_encoded_s msg_encoded;

#endif

// lib.c

#include "lib.h"

msg_encoded some_var;

// main.c

# include "lib.h"
int main(){
    msg_encoded some_other_var;
}

main.o:(.bss.msg_encoded_default+0x0): multiple definition of `msg_encoded_default'

Masoud Rahimi
  • 5,785
  • 15
  • 39
  • 67
  • 1
    [Variable declaration in a header file](//stackoverflow.com/a/1164190) – 001 Nov 23 '18 at 17:31
  • @JohnnyMopp Should I make both `msg_encoded_default` and `msg_encoded` extern? – Masoud Rahimi Nov 23 '18 at 17:33
  • 2
    If you are including that header file into more than one source module in your program, then each one is defining `msg_encoded_default`. You should define `msg_encoded_default` in one source module, then `extern` it in the header (`extern msg_encoded msg_encoded_default;`) – lurker Nov 23 '18 at 17:33
  • Possible duplicate of [How to avoid "multiple definition" error for global constants?](https://stackoverflow.com/questions/24717066/how-to-avoid-multiple-definition-error-for-global-constants) – Govind Parmar Nov 23 '18 at 17:35
  • 1
    The error is not caused by the typedef. It's caused by the `msg_encoded_default` variable. – 001 Nov 23 '18 at 17:37
  • 1
    Since you have the typedef, you could declare the `msg_encoded_default` variable using the typedef. E.g. declare `extern msg_encoded msg_encoded_default;` in "lib.h", and `msg_encoded msg_encoded_default = {{0}, 0};` in "lib.c". – Ian Abbott Nov 23 '18 at 17:40

1 Answers1

2

A "declaration" like

struct msg_encoded_s {
   ...
} msg_encoded_default;

is actually both (1) a definition of a struct-type named msg_encoded_s and (2) the definition of a variable of this type named `msg_encoded_default.

Hence, if you include this header file in separate translation units, then you will redefine a variable named msg_encoded_default, which is not allowed.

To overcome this, write a header like...

typedef struct msg_encoded_s
{
    uint8_t msg[10];
    int length;
} msg_encoded;

extern msg_encoded msg_encoded_default;

An in exactly one translation unit write:

#include "myheader.h"
msg_encoded msg_encoded_default = {{0}, 0};

In all other translation units just write...

#include "myheader.h"
...
int test = msg_encoded_default.length;  // or something like this
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Thank you, Why you set the default value in `.c` and not `.h`? – Masoud Rahimi Nov 23 '18 at 17:45
  • 1
    The default value is set where the variable is *defined*, while `extern msg_encoded msg_encoded_default;` is just a *declaration* – Stephan Lechner Nov 23 '18 at 17:46
  • 1
    +1 for good explain difference between declaration and definition of variable in C. [see Johnathan Leffler post] ( https://stackoverflow.com/a/1433387/7508077) – EsmaeelE Nov 23 '18 at 18:12