I am using an external library written in c. Our application code is written in c .
The application code try to use an include file which contains (very simplified) the following piece of code:
#pragma once
#pragma pack(push, 1)
struct someQueue
{
struct descExtra {
unsigned int ndescs;
} desc;
};
#pragma pack(pop)
static inline void someQueue_allocate(unsigned int num)
{
unsigned int someSize = sizeof(struct someQueue) num * sizeof(struct descExtra);
}
Now as said this is external code which I do not want to modify. When I include this header from a "C" file, it compiles. When I include this header file from a c file it gives me a compile error:
error: invalid application of 'sizeof' to an incomplete type descExtra
By declaring the structure inside the struct somequeue it is not accessible outside and therefore it cannot determine its size... i think? Moving this outside the somequeue struct and it will compile.
So is my understanding correct? Why is this allowed in C but not in C ?
Can I work around this or do I need to have a c wrapper to include this header and implementation (which I not prefer..)
CodePudding user response:
It's because struct descExtra
is not defined. someQueue::descExtra
is however defined, so instead do:
sizeof(someQueue::descExtra);
If you can't change the code to be valid for both C and C , you might want consider using a C compiler for the C code.
CodePudding user response:
This is allowed in C but not in C because these are two completely different programming languages.
In C this class is someQueue::descExtra
, descExtra
is a member of the someQueue
class. There is no class descExtra
when the shown code is parsed as C .
One possible solution is to deploy a liberal sprinkling of
#ifdef __cplusplus
in order to supply both C and C alternatives.
CodePudding user response:
You are partially right, In C when you declare nested struct, it's not accessible the same way as in C. C code:
struct A{
struct B{};
};
int main(void){
int size = sizeof(struct B); // Compiles fine
}
But in C , when you declare a nested structure, the structure that is not nested act like a namespace and therefore you can access the nested structure like this
C code:
struct A{
struct B{};
};
int main(void){
int size = sizeof(A::B); // Compiles fine
}
In C the "real" name of struct B
is actually A::B
.
CodePudding user response:
The problem is that descExtra
is a nested type and so when you write sizeof(struct descExtra)
, it declares a new class type descExtra
in the enclosing scope and then we try to apply sizeof
to this incomplete type which gives us the mentioned error.
A contrived example to clear this up further:
int main()
{
struct C{
struct P{};
};
//----------------vvvvvvvv--->this DECLARES a new class type called P in main()
std::cout<<sizeof(struct P);//error: invalid application of ‘sizeof’ to incomplete type ‘main()::P’
return 0;
}
So to solve this replace sizeof(struct descExtra)
with sizeof(struct someQueue::descExtra)
CodePudding user response:
It might be feasible to redefine struct descExtra
outside the header file:
header_wrapper.h
#ifndef HEADER_WRAPPER_H__INCLUDED
#define HEADER_WRAPPER_H__INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 1)
struct descExtra {
unsigned int ndescs;
};
#pragma pack(pop)
#include "header.h" // defines struct someQueue, struct someQueue::descExtra, and someQueue_allocate()
#ifdef __cplusplus
}
#endif
#endif /* HEADER_WRAPPER_H__INCLUDED */
It really depends on how complicated the real struct descExtra
is and what else it depends on.