0

I'm trying to include 3rd party libraries into the .c file but it gives either redefinition or conflicting types error since it has typedef structs with the same name.

I've tried to include guards after reading some answers here in SO and obviously directly changing the typedef on the .h file has solved the problem.

e.g. (Also have to change the functions return type)

// stack.h
typedef struct item stack_item;

// queue.h
typedef struct item queue_item;

However, the original code is as follows:

// stack.h
typedef struct item item;

// queue.h
typedef struct item item;

It throws the following error:

In file included from test.c:5:0:
Queues/queue.c:6:8: error: redefinition of ‘struct item’
 struct item {
        ^

In file included from Stacks/stack.c:4:0, from test.c:4:
Stacks/stack.h:6:16: note: originally defined here
 typedef struct item item;
                ^

I would like to know what is the standard way to solve this, instead of changing the definitions in the .h file

Renan Lopes
  • 411
  • 4
  • 16
  • 2
    include guards do not help if the same name is used in two different headers. – Osiris Dec 19 '18 at 16:52
  • 4
    I don't think there is a standard way. Library authors should think about such an issues and create unique names. Such as `stack_item_t` vs `queue_item_t` – Eugene Sh. Dec 19 '18 at 16:54
  • @EugeneSh. There is no way to fix this without changing the original code? – Renan Lopes Dec 19 '18 at 16:57
  • 2
    There is no way to prevent that kind of clashes. The usual is to prefix identifiers with something, hopefully, unique. Maybe, in your case, `struct item` should be either `struct RL_stack_item` or `struct RL_queue_item`. Also, in my opinion, do not pollute the global namespace with `typedef`s. – pmg Dec 19 '18 at 16:57
  • @pmg It means that I should use it as a struct without redefining its name? – Renan Lopes Dec 19 '18 at 17:05
  • 1
    Making wrapper libraries could possibly help. But it's too much hassle. – Eugene Sh. Dec 19 '18 at 17:05
  • 1
    In my opinion, library header files should not create `typedef`s. If the user of the library cannot type `struct foo_bar_xyz` let him do the `typedef struct foo_bar_xyz fbx` himself. – pmg Dec 19 '18 at 17:12
  • I'm not a big fan of `typedef`s myself, @pmg, but it does not appear that `typedef`s are the only problem here. There is a collision of structure tags as well, unless those two structure types somehow manage to be compatible, in the standard's sense of that term. – John Bollinger Dec 19 '18 at 17:30

1 Answers1

3

C has only one namespace for structure tags, which also contains the tags of unions and enumerations. You cannot use two different structure types with the same tag in the same scope. There is a different namespace that contains typedefed identifiers, among other things, but again, one type name can mean only one thing in any given scope.

However, in practice, structure names are significant only at compile time. If you are using packaged, pre-compiled versions of the third-party libraries then probably all you need to worry about is the headers. You might be able to use the preprocessor to change one or both of the tags within the scopes of your program's translation units. For example,

#define item stack_item
#include <stack.h>
#undef item

#define item queue_item
#include <queue.h>
#undef item

Your code would then use struct stack_item and / or the typedef stack_item for the one, and struct queue_item and / or queue_item for the other. Be aware that there is a risk of that having a broader effect than you want -- changing structure member names, for example. Additionally, although it has a decent chance to work, it is technically non-conforming to call any functions that have parameters or return types derived from or containing instances of the original structure types (with some caveats).

In the event that that does not work, you could also consider performing equivalent edits by hand to produce local versions of the headers for use by your project only. This would allow you to be more precise about what gets changed, but using these headers still suffers from the conformance issues described above.

If you must use both libraries in the same translation unit and you want to ensure that your code conforms to the standard, then you're out of luck. The only conforming alternative is to modify and rebuild one or both libraries so that they no longer have name collisions.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • I thought that different files wouldn't cause this conflict even with equal names. Something like `filename_struct` – Renan Lopes Dec 19 '18 at 17:23
  • 1
    @RenanLopes, there is no problem with using the same identifier for different things in different translation units. Formally, however, there *is* a problem with using different tags for supposedly the same structure type in different translation units, if objects of that type are in any way communicated between the two. – John Bollinger Dec 19 '18 at 17:28