Conflicting declaration in c++

22,885

Solution 1

In C, this:

struct abc
{
   int a1;
   int b1;
};

creates a type struct abc (roughly speaking), but not a type abc.

That's why you use the typedef trick to create a type we can use without having to write struct everywhere:

typedef struct abc{
   int a1;
   int b1;
} abc_t;

Now you have the type abc_t, too, which is the same as struct abc. There is still no type abc.

So when you add on the declaration of a pointer called abc, that's valid, as the name is not taken yet.


In C++, the original declaration creates a type named abc. There is no need for the typedef trick, and your declaration of a pointer called abc is invalid because the name abc is taken.


Solution

You can disambiguate your names (and de-obfuscate the code) like so:

struct abc
{
   int a1;
   int b1;
};
typedef struct abc abc_t;
abc_t* ptr_to_abc;

Or, if you are writing C++ and don't need C compat, just this:

struct abc
{
   int a1;
   int b1;
};

abc* ptr_to_abc;

Solution 2

You've declared abc as both a struct and a pointer to a struct by using typedef. It's the same as doing:

struct abc {...};
typedef abc abc_t; // ok, abc_t is now an alias for abc
typedef abc *abc;  // error

Skip the typedef, abc_t and *abc and use the class (with all members public per default) abc as-is.

i.h

struct abc {
    int a1 = 0;
    int b1 = 0;
};

void fun(const abc& x);

i.cpp

#include <iostream>
#include "i.h"

void fun(const abc& x) {
    std::cout << x.a1 << "\n";
}

main.cpp

#include <iostream>    
#include "i.h"

int main(){
    abc val;
    fun(val);
    return 0;
}

Solution 3

This

struct abc;

in C++ declares the type struct abc as well as the type abc, which then clashes with typedef'ing ...*abc again.

In C it just declares struct abc, so typedef'ing ...*abc does not produce a duplicate declaration.

Share:
22,885
Karthik K M
Author by

Karthik K M

Updated on January 26, 2020

Comments

  • Karthik K M
    Karthik K M over 4 years

    I have a cpp file as follows:

    #include <iostream> 
    
    #include "i.h"
    
    using namespace std; 
    
    typedef struct abc{
    int a1;
    int b1;
    } abc_t, *abc;
    
    void fun(abc x){
    cout<<x->a1;
    }
    
    int main(){
    abc val;
    fun(val);
    return 0;
    }
    

    The i.h file :

    struct abc;
    
    void fff(struct abc);
    

    When I am compiling the code following error occurs:

    t.cpp:8: error: conflicting declaration ‘typedef struct abc* abc’
    
    t.cpp:5: error: ‘struct abc’ has a previous declaration as ‘struct abc’
    
    t.cpp: In function ‘void fun(abc)’:
    
    t.cpp:11: error: base operand of ‘->’ has non-pointer type ‘abc’
    

    If I save the cpp file as c file and compile using c compiler then everything works fine. What is the issue with c++ compiler?

    • Karthik K M
      Karthik K M over 5 years
      @alk I have edited the question
    • Chris Turner
      Chris Turner over 5 years
      Why are you declaring the struct in the cpp file and not the header file?
    • KamilCuk
      KamilCuk over 5 years
      This is not C, it's C++. And in C++ you can't have typedef struct abc {} *abc;
  • Karthik K M
    Karthik K M over 5 years
    I didn't get it
  • Bob Bills
    Bob Bills over 5 years
    typedef struct StructNAME {...} typedefNAME, otherTypedefNAME; you can't have the same name for the struct and the typedef at the same time.
  • Eljay
    Eljay over 5 years
    @KarthikKM • You cannot have the same identifier mean two different things.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 5 years
    @TedLyngmo Because the OP asked why it worked in C but not C++. You can't answer that without comparing the two.
  • Ted Lyngmo
    Ted Lyngmo over 5 years
    Ahhh... I didn't notice until now. Just saw rhe C++ tag and probably filtered out the C part. Good catch.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 5 years
    @Ted Can't blame you 😂