Sizeof Struct Member at Compile Time Trick Not Working - c

Found this answer here:
sizeof a struct member
Copied it completely into my code, but my compiler objects that I have a pointer to an incomplete class type.
uint8_t clStructCount = sizeof(((struct ALMConfStr *) 0)->IntelRecsPerPg);
What am I doing wrong? I want to set clStructCount equal to the value of IntelRecsPerPg at runtime; I thought this was the trick to do so.
Thanks!

The definition of your structure needs to be visible at the point where the compiler encounters your sizeof code.
So, this translation unit should work:
struct ALMConfStr {
int IntelRecsPerPg[MagicNumber];
};
// ...
uint8_t clStructCount = sizeof(((struct ALMConfStr *) 0)->IntelRecsPerPg);
whether it's all in one file, or the struct is in a header #included before your sizeof code.
However, this:
struct ALMConfStr;
// ...
uint8_t clStructCount = sizeof(((struct ALMConfStr *) 0)->IntelRecsPerPg);
won't work, because the compiler doesn't know what a struct ALMConfStr consists of, or what an IntelRecsPerPg might be in that context.

From a comment on Useless' answer:
From my header file:
typedef struct ALMConfStruct {
uint8_t updateMode;
uint8_t flashPgSize;
uint8_t flashMaxPagesSize;
uint8_t IntelRecsPerPg;
fptr_t appResetAddr;
uint16_t appEndAddr;
uint8_t comIntf;
}ALMConfStr;
Your struct tag is ALMConfStruct and not ALMConfStr, so
struct ALMConfStr
declares a new incomplete struct type. Remove the struct, or use struct ALMConfStruct in your code to determine the size.
uint8_t clStructCount = sizeof(((ALMConfStr *) 0)->IntelRecsPerPg);
or
uint8_t clStructCount = sizeof(((struct ALMConfStruct *) 0)->IntelRecsPerPg);

I think there is no definition of struct ALMConfStr
or IntelRecsPerPg is not a member of struct ALMConfStr
Say
struct ALMConfStr{
//some member variables
data_type IntelRecsPerPg;
//some more member variables
};
Basically sizeof(((struct ALMConfStr *) 0)->IntelRecsPerPg) tries to get the
sizeof(IntelRecsPerPg)
in the structure assuming that the structure is available at address 0.

Related

Dereferencing pointer to incomplete type while using nested structs

I'm using a library developed by Xsens in order to use in my project their mti710-GNSS-INS. This library has the following structures (inside the headers xbusmessage.h xbusparser.h)
struct XbusParser {
struct XbusParserCallback callbacks;
struct XbusMessage currentMessage;
uint16_t payloadReceived;
uint8_t checksum;
enum XbusParserState state;
};
struct XbusParserCallback{
void* (*allocateBuffer)(size_t bufSize);
void (*deallocateBuffer)(void const* buffer);
void (*handleMessage)(struct XbusMessage const* message);
};
struct XbusMessage{
enum XsMessageId mid;
uint16_t length;
void* data;
};
In my code, I have a struct XbusParser* xSensBusParser; as a global variable.
Every time I try to access any field of the "parser struct" I get the following error: error: dereferencing pointer to incomplete type. Below an example code:
bool mti710WakeUp(struct XbusParser* parser, const uint32_t timeout_ms){
mti710ReadData(parser, sizeof(struct XbusMessage));
blockingDelay(timeout_ms, TIME_MS);
return parser->currentMessage.mid == XMID_Wakeup ? true : false;
}
Note that in mti710ReadData there is a UART Read function that fills a buffer and then a parsing function that changes the parser fields according to the received buffer.
As suggested by #Lundin in the comments above, there is a hidden struct definition in xbusparser.c while in the related header file there is only a
struct XbusParser;
So I moved the definition from the .c to the .h file and it works well.
Regards.

Why type struct BMPFILE_ is incomplete? in C

in bmpfile.h I define struct:
struct BMP_FILE_ {
BMPHEADER header;
BITMAPINFOHEADER dib;
unsigned char channels;
rgb_px_t **pixels;
rgb_px_t *pal;
} BMPFILE_, *pBMPFILE;
typedef struct BMPFILE_ BMPFILE;
BMPFILE * bmp_create(uint32_t width, uint32_t height, uint32_t depth, uint32_t fillcolor);
bmpfile.c defines function bmp_create_standard_color_table
static void
bmp_create_standard_color_table(BMPFILE *bmpfile)
{
switch (bmpfile->dib.depth) ...
}
Error: dereferencing pointer to incomplete type on line with switch ...
First of all, why the type BMPFILE_ is incomplete?
It's not clear to me why I need another name for type BMPFILE_.
typedef struct BMPFILE_ BMPFILE;
Originally I wanted to skip it and use just BMPFILE_ as return type for function bmp_create, but there was an error that the BMPFILE_ is unknow.
I believe this means that the type is incomplete, but I added the
typedef struct BMPFILE_ BMPFILE;
and the result is that it can pass the header through compiler, but there is another error in the .c file. But I cannot find out why this happens.
In main function I tried to use this:
BMPFILE bmpfile; instead of BMPFILE * bmpfile;
and again it tells me I cannot do it because the type is incomplete. But definitely I cannot find why it is incomplete. Because I compared it with another very similar type declared as PNG_DATA data; (libpng). None problems with data type, even that both are having similar structure. I even tried to remove the sub-structs from BMPFILE_ (BMPFILE) to test if it will be complete or incomplete type and it was still incomplete.
You are confused by using too many similar names (e.g. BMPFILE_ vs BMP_FILE_ ....), which makes your code unreadable. And you made a typo, which confuses the compiler.
Forward declare
struct BMP_FILE_st;
Then
typedef struct BMP_FILE_st BMP_FILE;
Then define your structure:
struct BMP_FILE_st {
BMPHEADER header;
BITMAPINFOHEADER dib;
unsigned char channels;
rgb_px_t **pixels;
rgb_px_t *pal;
};
And don't make a typedef for pointer; So code BMP_FILE*, e.g. declare a pointer variable
BMP_FILE* ptr_bmp_file;
and an aggregate variable:
BMP_FILE my_bmp_file_struct;

Location of the struct when only the location of a member is given

Let us assume there is a struct with multiple members. The struct members are initialized with some values. The memory location of a specific member is given. Assume that you don't know the other members, their types, the ordering of members etc. Is there a way to know the memory location of the struct itself?
Is this problem called a specific name?
If you know the name of the struct, simply use offsetof
struct my_struct {
const char *name;
struct list_node list;
};
int main() {
struct my_struct t;
struct list_node* pl = &t.list;
size_t offset = offsetof(struct my_struct, list); //here
struct my_struct* pt = (struct my_struct*)((unsigned char*)pl-offset); //and here
}
If offsetof is not viable for what you're doing, then no, there's no other way. Offsetof can alternatively be written in standard C, but there's absolutely no good reason to do that.
If you know the structure type, then all you need is an offset of the field within the structure, subtract it from the member address and typecast result to pointer to the structure. For a practical implementation see FreeBSD's implementation of __containerof().
Hi Everyone I found the answer this
Cast a null pointer to the struct. You can get the offset by casting the resulting address(Offset) to a char*
(char *)(&((struct *)0)->member))
You could do any type*. But char* guarantees it's always the word size.
This should be how offsetof() is written as well

What does `*` mean in a C `typedef struct` declaration?

I'm looking at a C struct with some syntax I've never seen before. The structure looks like this:
typedef struct structExample {
int member1;
int member2
} * structNAME;
I know that normally with a structure of:
typedef struct structExample {
int member1;
int member2
} structNAME;
I could refer to a member of the second struct definition by saying:
structNAME* tempStruct = malloc(sizeof(structNAME));
// (intitialize members)
tempstruct->member1;
What does that extra * in the the first struct definition do, and how would I reference members of the first struct definition?
It means the defined type is a pointer type. This is an equivalent way to declare the type:
struct structExample {
int member1;
int member2;
};
typedef struct structExample * structNAME;
You would use it like this:
structNAME mystruct = malloc (sizeof (struct structExample));
mystruct->member1 = 42;
The typedef makes these two statements the same
struct structExample *myStruct;
structName myStruct;
It makes structName stand for a pointer to struct structExample
As an opinion, I dislike this coding style, because it makes it harder to know whether a variable is a pointer or not. It helps if you have
typedef struct structExample * structExampleRef;
to give a hint that it is a pointer to struct structExample;
structNAME is defined as a pointer on struct structExample. SO you can do
structNAME tempStructPtr = malloc(sizeOf(struct structExample));
tempStructPtr->member1 = 2;
The secret to understanding these is that you can put typedef in front of any declaration, to turn TYPENAME VARIABLENAME into typedef TYPENAME ALIASEDNAME.
Since the asterisk can't be part of the VARIABLENAME part if this was a plain declaration, it has to be part of the type. An asterisk following a type name means "pointer to" the preceding type.
Compare this:
typedef int * my_int_pointer;
It's exactly the same, except in your case instead of int you're declaring a struct.
In that case (* structNAME) is pointer variable of that structure..

Array of pointers to different structs

It is possible to do something like this How can I initialize an array of pointers to structs?
but with different structs?
E.g.
static struct structA_t a = {"ads", "as"};
static struct structB_t b = {"zzds", "dfr", "shywsd"};
static struct structC_t c = {"ssa", "ad", "dhksdhs"};
struct some_type *array[] = { &a, &b, &c};
How some_type will look like?
You could define some_type as a union:
typedef union{
struct structA_t;
struct structB_t;
struct structC_t;
}some_type;
This will lead you to the problem that you don't know what's actually contained in which element in the array.
To overcome this, add another field specifying the content that is used:
/* numbers to identify the type of the valid some_type element */
typedef enum my_e_dataId{
dataid_invalid = 0,
dataid_a,
dataid_b,
dataid_c
} my_dataId;
typedef union u_data {
struct structA_t* a;
struct structB_t* b;
struct structC_t* c;
}mydata;
typedef struct s_some_type{
my_dataId dataId;
mydata myData;
}some_type;
Then you could initialize your array as follows:
some_type sta[] = {
{dataid_a, (struct structA_t*) &a},
{dataid_b, (struct structA_t*) &b},
{dataid_c, (struct structA_t*) &c}
};
When you loop over the elements of array, first evaluate dataId so that you know what's contained in myData. Then, for example, access the data of the first element using
sta[0].myData.a->FIELDNAME_OF_A_TO_ACCESS
or the third element with
sta[2].myData.c->FIELDNAME_OF_C_TO_ACCESS
See this ideone for a working example: http://ideone.com/fcjuR
In C this is possible with void pointers (Replace "struct some_type" with "void"), but you really shouldn't be doing this. Arrays are for programming with homogeneous data.

Resources