structs and referring to them two different ways - c

I am reading someone's code I do not understand why he is referencing inside each union below differently.
-On the first one, he is able to reference inside by typing pwr_cmd.EN1
-On the second one, he is able to reference inside by typing errors.Bits.ERR1
-If I remove the Bits from the second one, will I be able to reference inside the the same way as the first one: errors.ERR1? -What is the difference between the two and why would you do one over the other? Thank you.
typedef union {
byte Byte;
union {
struct {
byte EN1 :1;
byte EN2 :1;
byte EN3 :1;
byte EN4 :1;
byte :4;
};
struct {
byte :2;
byte EN34 :2;
byte :4;
};
struct {
byte :2;
byte EN3r:1;
byte EN4r:1;
byte :4;
};
};
} pwr_cmd;
typedef union {
word Word;
union {
struct {
byte ERR1 :1;
byte ERR2 :1;
byte ERR3 :1;
byte ERR4 :1;
byte ERR5 :1;
byte ERR6 :1;
byte ERR7 :1;
byte ERR8 :1;
byte ERR9 :1;
byte DET1 :1;
byte DET2 :1;
byte FAIL1 :1;
byte PWR1 :1;
byte PWR2 :1;
byte PWR3 :1;
byte PWR4 :1;
} Bits;
nibble4 Nibble4;
};
} errors;

This is an example of a bitfield - each variable with a ":" represents a certain number of bits of an integer. This bitfield is unionized to allow the same bit positions to be named differently depending on context.
You would access one union member over another for clarity and to denote the intention of your code - this is a good way to self-document code, by creating meaningful names instead of something meaningless like "bit 4".
Re-reading your question - the difference between the two is that one uses named structs and the other doesn't. In the first, the members of the structs can be accessed without doing a struct member reference ("."), because they have no name. In the second, he declares a struct with a name, so the struct member reference is used. In my opinion the second is more clear, but the first is more concise. It's a matter of style and preference.

Related

Size of struct dependent of the position a union is placed within

I have following problem: In my code example, the too_long_CommandFrameStruct shows a size of 5, wheras all members added together have the size of 4. If I change the position of the union member to be first (like in shorter_CommandFrameStruct), the size is, like expected, 4.
Why does this happen and how can I prevent this? I'd like to have the order of the struct members as-is, because the struct gets byte-by-byte written to a (4-byte long) SPI buffer frame.
With the 5-byte long struct I have problems, because a nibble gets added between the unsigned int crc member and the union Commands cmdData. This nibble is probably causing the struct to grow to 4.5 and thus 5 bytes.
The code can be executed in an online compiler, like e.g. https://www.tutorialspoint.com/compile_c_online.php
#include <stdio.h>
#include <stddef.h>
union UnspecificFrame_t
{
unsigned short RegValue;
struct /* Single Bits */
{
unsigned bit0 :1;
unsigned bit1 :1;
unsigned bit2 :1;
unsigned bit3 :1;
unsigned bit4 :1;
unsigned bit5 :1;
unsigned bit6 :1;
unsigned bit7 :1;
unsigned bit8 :1;
unsigned bit9 :1;
unsigned bit10 :1;
unsigned bit11 :1;
unsigned bit12 :1;
unsigned bit13 :1;
unsigned bit14 :1;
unsigned bit15 :1;
} __attribute__((packed, aligned(1))) Bits;
};
union Commands
{
union UnspecificFrame_t unSpecFrame;
};
/* This one should be 4 bytes long, but actually is 5 bites long */
struct too_long_CommandFrameStruct
{
unsigned int crc :4;
union Commands cmdData;
unsigned int cmdType :4;
unsigned int id :8;
}__attribute__((packed, aligned(1))) too_long_CommandFrameStruct_t;
/* When switching the first members, the size is right */
struct shorter_CommandFrameStruct
{
union Commands cmdData;
unsigned int crc :4;
unsigned int cmdType :4;
unsigned int id :8;
}__attribute__((packed, aligned(1))) shorter_CommandFrameStruct_t;
int main()
{
printf("why is this size: %d\n", sizeof(too_long_CommandFrameStruct_t)); // returns 5
printf("and this one size: %d?\n", sizeof(shorter_CommandFrameStruct_t)); // returns 4
return 0;
}
In C, objects other than bit-fields are represented with whole numbers of bytes. And the members of a structure are required to be in order in memory in the same order they are declared in the structure.
When unsigned int crc :4;, it does not have to fill a full byte, because it is a bit-field, but it does have to be inside one or more bytes that are used for it. Then union Commands cmdData follows that and takes two bytes. Then unsigned int cmdType :4; and unsigned int id :8; require 12 more bits, so that requires at least two bytes (presuming bytes are eight bits, as is common). So declaring the members requires at least five bytes.
Note that alignment is not even consider in the above; five bytes are required simply because you need one byte, then two, then two more.
When union Commands cmdData is first, it requires two bytes. Then the three bit-fields that follow it take 4+4+8 = 16 bits, which only need two more bytes. So the total is four bytes.

How to check whether two structure types are equal in c?

I have a bit-field structure "struct errors" of size 1 byte and I am using its data using a mask "ERR_MASK" as shown in below code.
My requirement is that if the type of the structure is changed, the mask need to be adapted accordingly.
Since I am importing this structure type from another component or module (file1.h in below code),
I want to define a copy of this structure type "struct copy_errors" in my source file (file2.c in below code) and check if it has got changed with original type in file1.h,
If there is a mismatch, I want to throw an compilation error from file2.c. Can anyone tell me how do I achieve this? Or is there any other way to do this?
Note: I don't want to access "struct errors" with its elements.
/*file1.h*/
struct errors
{
unsigned char err0 :1;
unsigned char err1 :1;
unsigned char err2 :1;
unsigned char err3 :1;
unsigned char err4 :1;
unsigned char err5 :1;
unsigned char reserved1 :1;
unsigned char reserved2 :1;
};
/*file2.c*/
#include "file1.h"
#define ERR_MASK 0xFCU
struct copy_errors
{
unsigned char err0 :1;
unsigned char err1 :1;
unsigned char err2 :1;
unsigned char err3 :1;
unsigned char err4 :1;
unsigned char err5 :1;
unsigned char reserved1 :1;
unsigned char reserved2 :1;
};
bool function(struct err*)
{
bool ret=0;
unsigned char * err_ptr;
err_ptr = (unsigned char *) err;
if (((*err_ptr) & ERR_MASK) != 0U)
{
ret = 1;
}
return ret;
}
C doesn't support anything equivalent. If you have a tool chain that supports custom build events, you could introduce a pre-build step calling e. g. a python script (or any other language you prefer). This script then would:
load the header file
iterate over all lines until it finds the structure in question
check for all known members in desired order (i. e. no members replaced)
finally check, if end of structure is reached (i. e. no new members added)
If your tool chain stops, if the pre-build task fails, you are out already (just return 0 on success and anything else on failure), otherwise you could create a simple C-File, empty on success and containing an #error directive on failure.
Within your C code, you could additionally assure that the size of your struct matches:
#define CONCATENATE(X, Y) CONCATENATE_(X, Y)
#define CONCATENATE_(X, Y) X##Y
#define STATIC_ASSERT(CONDITION) \
typedef int(CONCATENATE(_static_assert_, __LINE__))[(CONDITION)? 1 : -1]
STATIC_ASSERT(sizeof(struct errors) == sizeof(unsigned char));
The macro is defined to be re-usable, as is, though, might produce additional warnings if used within function body (because of unused local type).

C struct vs union in regard to bitfields

Admittedly this is a very silly question, but one that I was thinking about the other day. Sometimes in source I see registers defined like so:
union
{
uint8_t byte;
struct
{
uint8_t bit1 :1;
uint8_t bit2 :1;
uint8_t bit3_4 :2;
uint8_t rsvd :4;
} bitfield;
} SomeReg_t;
Other times I see just a standard struct:
struct
{
uint8_t bit1 :1;
uint8_t bit2 :1;
uint8_t bit3_4 :2;
uint8_t rsvd :4;
} SomeReg_t;
I wrote a quick example to show what I mean:
https://onlinegdb.com/r1H3Xuqe4
The question is, in regard to bitfields, what are the differences in these two definitions. When would you use one vs the other for bitfields.
It is easy to explain
Union is handy if you want to read or assign the whole byte as well.
for example
typedef union
{
uint8_t byte;
struct
{
uint8_t bit1 :1;
uint8_t bit2 :1;
uint8_t bit3_4 :2;
uint8_t rsvd :4;
} bitfield;
} SomeReg_t;
SomeReg_t reg;
reg.bitfield.bit1 = 1;
/*...*/
printf("The reg value is %hhx\n", reg.byte);
reg.byte = ReadFormPeriph();
if(reg.bitfield.rsvd == 0b1011)
{
/* do something */
}

Linking struct/union member to another struct/union member

I am somewhat new to C in regards to structures, unions and bitfields and need help. Below is the SLPH_CONTROL which will "control" the bits in the destination of DRVCONF0 and DRVCONF1. After the code snippet I will explain what I need.
/* SLPH_CONTROL **********************************************/
typedef union
{
struct
{
unsigned int SH0_BIT0 :1;
unsigned int SH0_BIT1 :1;
};
uint8 SLPH_CONTROL_byte;
} SLPH_CONTROL;
SLPH_CONTROL my_SLPH_CONTROL;
/* DRVCONF0 **********************************************/
typedef union
{
struct
{
unsigned int DF0_BIT0 :1;
unsigned int DF0_BIT1 :1;
unsigned int DF0_BIT2 :1;
unsigned int DF0_BIT3 :1;
unsigned int DF0_BIT4 :1;
};
uint8 DRVCONF0_byte;
} DRVCONF0;
DRVCONF0 my_DRVCONF0;
/* DRVCONF0 **********************************************/
typedef union
{
struct
{
unsigned int DF1_BIT0 :1;
unsigned int DF1_BIT1 :1;
unsigned int DF1_BIT2 :1;
unsigned int DF1_BIT3 :1;
unsigned int DF1_BIT4 :1;
};
uint8 DRVCONF1_byte;
} DRVCONF1;
DRVCONF1 my_DRVCONF1;
Now with the code above I want to link or copy data from and to like so:
SH0_BIT0:1 to DF0_BIT4:1;
SH1_BIT1:1 to DF1_BIT0:1;
Is there a way to do this? I am really lost and looked everywhere online for a solution to this. Any suggestions are welcome!!!
Thanks,
Eric
Maybe this is possible on special embedded H/W (I don't know) but not on a regular PC with standard C.
Bit fields describe individual bits in one or more consecutive bytes. Actually, bytes are addressable but bits are not. The read/write access to bits is internally solved by bit-wise operations (like in C expressed with &, |, ^, ~).
my_DRVCONF0 and my_DRVCONF1 are individual variables in your sample. Thus, it's even not granted that they will be allocated/stored in consecutive memory. (They definitely will not if some kind of word-alignment is enabled.)
You probably have to make the control more sophisticated (e.g. providing pairs of address and bit index) to do what's intended.

Why does this Union take up 2 bytes even though I'm aligning to one

I'm modeling a LCD hitachi display parallel port connection (for those interested HD44780, in 4 bit mode).
Even though alignment is set to 1,this union still takes up 2 bytes. If I get rid of the msnibble struct (directly put db4 to db7 in the struct in the union) it takes up 1 byte. Can structs take up less than 1 byte if they're inside a union? Is the 2 bytes the result of the msnibble taking up 1 byte plus the nibble (the enable bit,rs bit and the two blank bits), thus making the size 2 bytes?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t byte_t;//could have used char
#pragma pack(push,1)
typedef union
{
byte_t whole_port :8;
struct
{
byte_t enable :1;
byte_t rs :1;
byte_t :1;
byte_t :1;
struct
{
byte_t db4 :1;
byte_t db5 :1;
byte_t db6 :1;
byte_t db7 :1;
}msnibble;
};
} para_port_t;
#pragma pack(pop)
int main(int argc, char** argv) {
printf("%u\n",sizeof(para_port_t));
return (EXIT_SUCCESS);
}
I'm working from netbeans in ubuntu compiling with gcc. As pragma is a compiler directive I wanted to know if it's the same in Microsoft Visual Studio?
Your final question asks if MSVC has 2 bytes for the union: yes it does.
Your union has one variant as struct nested within struct. How could that be 1 byte? Without the union,
#pragma pack(push,1)
typedef struct {
byte_t enable :1;
byte_t rs :1;
byte_t :1;
byte_t :1;
struct
{
byte_t db4 :1;
byte_t db5 :1;
byte_t db6 :1;
byte_t db7 :1;
}msnibble;
} thatstruct;
#pragma pack(pop)
has a size of 2. Where does it say that nested structs can be packed into 1 byte?
Can structs take up less than 1 byte if they're inside a union?
Nope. Your nested struct takes a full byte, and your outer struct rounds up to two bytes.

Resources