Home > other >  invalid application of 'sizeof' to an incomplete type
invalid application of 'sizeof' to an incomplete type

Time:08-09

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.

  •  Tags:  
  • c c
  • Related