2

main.c

#include "stackg.h"

int main()
{
    return 0;
}

stackg.h

#ifndef STACKG_H
#define STACKG_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct stack_gt* stack_gt;

stack_gt stkg_init(
                  void* (*alloc)(const void* data, const int size),
                  void (*dealloc)(void* data),
                  void (*copy)(void* data_d, const void* data_s),
                  const int size
                  );
void stkg_free(stack_gt s);
int stkg_is_empty(stack_gt s);
int stkg_is_full(stack_gt s);
const int stkg_size(const stack_gt s);
void stkg_clear(stack_gt s);
int stkg_push(stack_gt s, const void* data);
int stkg_pop(stack_gt s, void* data);
int stkg_peek(stack_gt s, void* data);

#ifdef __cplusplus
}
#endif

#endif

The above program compiles successfully with the GCC compiler, but in MSVC2008 it gives the following error :

error C2040: 'stack_gt *' differs in levels of indirection from 'stack_gt'

What should I tell MSVC to make it compile the program without changing anything in the code?

Edit

Error occurs at line 8 of stackg.h :: typedef struct stack_gt* stack_gt;

Edit 2

If nothing else, I'll go with typedef struct _stack_gt* stack_gt;

Jonas
  • 1,019
  • 4
  • 20
  • 33

2 Answers2

2

The problem is that here:

typedef struct stack_gt* stack_gt;

you are giving stack_gt a different type, while this works fine:

typedef struct stack_gt* stack_gtB;

clang gives us a nicer error message:

error: typedef redefinition with different types ('struct stack_gt *' vs 'stack_gt')

This is covered in the draft C++ standard section 7.1.3 The typedef specifier paragraph 6:

In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [ Example:

class complex { / ... / };
typedef int complex; // error: redefinition

—end example ]

Using the same name though is fine, so this would be ok:

   typedef struct stack_gt stack_gt;

covered in paragraph 3:

In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:

typedef struct s { / ... / } s;
typedef int I; 
typedef int I;
typedef I I;

—end example ]

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Shafik Yaghmour is right, I tried to compile it as `C++` , clang complained... Ignore my comments here – Gábor Buella Mar 30 '14 at 02:47
  • of course it will work if I changed `stack_gt` to something else, but that forces me to change other things in the code. I don't want to do that as I have other structures that follow the same style. I was asking if I can make MSVC compile this without introducing changes to the code. I guess there's no other way. – Jonas Mar 30 '14 at 02:50
  • @Jonas a standards compliant C++ compiler will not allow this `gcc` and `clang` also reject this code, so Visual Studio is doing the correct thing. Although compiling using a C compiler is the only way I can see this working but that would require some reworking of the code anyway. – Shafik Yaghmour Mar 30 '14 at 03:01
  • @Jonas is there anything I can add to my answer to make it more helpful? – Shafik Yaghmour Nov 06 '14 at 17:32
1

Another idea:

 #ifdef __cplusplus

 extern "C" {
 typedef void * stack_gt

 #else

 typedef struct stack_gt* stack_gt;

 #endif

This is ugly, but you don't need to rewrite any other part of the code, only this header included in C++ . It is only used as an opaque pointer in C++ anyways, and C doesn't notice.

Gábor Buella
  • 1,840
  • 14
  • 22