In the following example I expect the size of complex_t to be the same as uint16_t: 2 bytes, however it's 3 bytes.
Removing the second union ("proximity_unsafe") reduces the size to 2 bytes, but I can't figure out the model of the packing rules.
#include <stdint.h>
#include <stdio.h>
typedef union {
uint16_t unsafe;
struct {
uint16_t backwardmotion_unsafe : 1;
uint16_t batteryvoltage_unsafe : 1;
union {
uint16_t dropoff_unsafe : 4;
struct {
uint16_t dropofffrontleft_unsafe : 1;
uint16_t dropofffrontright_unsafe : 1;
uint16_t dropoffsideleft_unsafe : 1;
uint16_t dropoffsideright_unsafe : 1;
}__attribute__((__packed__));
}__attribute__((__packed__));
union {
uint16_t proximity_unsafe : 3;
struct {
uint16_t proximityfront_unsafe : 1;
uint16_t proximityleft_unsafe : 1;
uint16_t proximityright_unsafe : 1;
}__attribute__((__packed__));
}__attribute__((__packed__));
} __attribute__((__packed__));
} __attribute__((__packed__)) complex_t;
int main()
{
printf("sizeof(complex_t): %i", sizeof(complex_t));
printf("sizeof(uint16_t): %i", sizeof(uint16_t));
}
Because it is legal to take the address of any named struct member that is not a bitfield, such non-bitfield members are required to start at byte boundaries. While it is not possible to take the address of anonymous members, and it would thus theoretically be possible for a compiler to allow such objects to start at arbitrary bit boundaries, that would imply that the layout of a structure would vary based upon whether its members were named.
Related
My bitfield below represents the 7 status flags for the 6502 CPU. I am trying to emulate the instruction php, which pushes a copy of the status flags onto the stack.
struct Flags {
uint8_t C: 1;
uint8_t Z: 1;
uint8_t I: 1;
uint8_t D: 1;
uint8_t V: 1;
uint8_t N: 1;
uint8_t B: 2;
};
I need a way to pack each field into a single-byte datatype like uint8_t so that I can push it to the stack. However, the code below gives this error: operand of type 'struct Flags' where arithmetic or pointer type is required. How do I resolve this problem?
int main() {
struct Flags f = {0, 0, 0, 0, 1, 0, 0};
uint8_t f_as_byte = (uint8_t) f;
}
The problem with bitfields is that it is implementation-defined in what order the bits are laid out. This could be rather unacceptable for a 6502 emulator. The PHP command must push the status word in the exact desired format, i.e. something like
uint8_t as_state = f.N << 7 | f.V << 6 | f.B << 4 | f.D << 3 | f.I << 2 | f.Z << 1 | f.C;
Your layout is wrong, the B member is in wrong position. All in all considering the complex code like one above, maybe it would be easier to just consider the flags as a single uint8_t and have access macros for it, something like
#define FLAG_N 0x80U
...
#define FLAG_C 0x1U
#define SET_FLAG(flag_var, flag) ((flag_var) |= (flag))
#define CLR_FLAG(flag_var, flag) ((flag_var) &= ~(flag))
#define GET_FLAG(flag_var, flag) ((_Bool)((flag_var) & (flag)))
uint8_t flags = 0;
SET_FLAG(flags, FLAG_C);
if (GET_FLAG(flags, FLAG_N)) { ... }
That way the PHP instruction can be coded to just push flags as is...
Except that the B flag that is pushed is not a flag from the status register...
You can do it with a union:
typedef unsigned char uint8_t;
struct Flags {
uint8_t C:1;
uint8_t Z:1;
uint8_t I:1;
uint8_t D:1;
uint8_t V:1;
uint8_t N:1;
uint8_t B:2;
};
union uFlags {
uint8_t B;
struct Flags F;
};
int
main()
{
struct Flags f = { 0, 0, 0, 0, 1, 0, 0 };
union uFlags u;
u.F = f;
uint8_t f_as_byte = u.B;
}
With a designated initializer, you may be able to initialize the union directly without a separate f:
typedef unsigned char uint8_t;
struct Flags {
uint8_t C:1;
uint8_t Z:1;
uint8_t I:1;
uint8_t D:1;
uint8_t V:1;
uint8_t N:1;
uint8_t B:2;
};
union uFlags {
uint8_t B;
struct Flags F;
};
int
main()
{
union uFlags u = {
.F = { .V = 1 }
};
uint8_t f_as_byte = u.B;
}
Instead of casting the structure as a (uint8_t), you should take its address and cast that as a (uint8_t *):
#include <stdio.h>
struct Flags {
uint8_t C: 1;
uint8_t Z: 1;
uint8_t I: 1;
uint8_t D: 1;
uint8_t V: 1;
uint8_t N: 1;
uint8_t B: 2;
};
int main() {
struct Flags f = {0, 0, 0, 0, 1, 0, 0};
uint8_t f_as_byte = *(uint8_t *)&f;
printf("flags: %.2X\n", f_as_byte);
return 0;
}
Note however that the actual bit values used to represent the bit-field members are implementation defined. The C Standard does not even guarantee that the Flags structure fit in a single byte. This make bit-fields a risky choice to represent hardware registers or instruction opcodes as a would make the emulator non-portable. Little-endian and big-endian systems typically use a different layout for bit-fields members.
I have an array of unsigned 16-bit integers:
static uint16_t dataArray[7];
The bits of the 7th element of the array represents some kind of status. I want to get and set the values of this status in an easy way, without bit shifting and without having to copy a new value to the array every time the status changes. So I created a union with a struct, and a pointer:
typedef struct {
unsigned statusCode : 4;
unsigned errorCode : 4;
unsigned outputEnabled : 1;
unsigned currentClip : 1;
unsigned : 6;
} SupplyStruct_t;
typedef union {
SupplyStruct_t s;
uint16_t value;
} SupplyStatus_t;
static SupplyStatus_t * status;
My initialisation routine wants the status pointer to point to the 7th element of the array, so I tried:
status = &(dataArray[6]);
Although this works, I get a warning: assignment from incompatible pointer type
Is there a better way to do this? I cannot change the array, but I am free to change the structure, the union or the pointer to the array..
Change unsigned to uint16_t
why? - test the difference:
https://ideone.com/uHLzpV
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint16_t statusCode : 4;
unsigned errorCode : 4;
unsigned outputEnabled : 1;
unsigned currentClip : 1;
unsigned : 6;
} SupplyStruct_t;
typedef struct {
uint16_t statusCode : 4;
uint16_t errorCode : 4;
uint16_t outputEnabled : 1;
uint16_t currentClip : 1;
uint16_t : 6;
} SupplyStruct_t1;
typedef union {
SupplyStruct_t s;
uint16_t value;
} SupplyStatus_t;
typedef union {
SupplyStruct_t1 s;
uint16_t value;
} SupplyStatus_t1;
int main(void) {
printf("%zu %zu\n", sizeof(SupplyStatus_t), sizeof(SupplyStatus_t1));
return 0;
}
The most correct way is to declare the table as table of structs.
If not :
If you want too work on the bitfields you do not actually have to declare the pointer.
static SupplyStatus_t status;
status.value = dataArray[6];
and it is almost portable and safe way
you can also cast it explicitly
The warning says that uint16_t* is not compatible with SupplyStatus_t*.
If you want to get rid of this warning, cast it to SupplyStatus_t*:
status = (SupplyStatus_t*)&(dataArray[6]);
I also would put the union and struct together:
typedef union
{
struct
{
unsigned statusCode : 4;
unsigned errorCode : 4;
unsigned outputEnabled : 1;
unsigned currentClip :1;
unsigned unused : 6;
} s;
uint16_t value;
} SupplyStatus_t;
I know this question is asked tons of times, but I cannot seem to link it to my problem.
My problem is something to do with filling out a web of structs
Here is my buggy code
src\fpu.c:17:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.control = 0x37F;
^
This is the buggy code in a function
void fpuInit(struct emu_cpu *cpu) {
cpu->instr.fpu.control = 0x37F;
cpu->instr.fpu.status = 0;
cpu->instr.fpu.tag = 0xFFFF;
cpu->instr.fpu.lastDataPointer = 0;
cpu->instr.fpu.lastDataSeg = 0;
cpu->instr.fpu.lastIP = 0;
cpu->instr.fpu.lastIPseg = 0;
cpu->instr.fpu.opcode = 0;
}
Here is how the struct web looks like
cpu
struct emu_cpu
{
struct emu *emu;
struct emu_memory *mem;
uint32_t debugflags;
uint32_t eip;
uint32_t eflags;
uint32_t reg[8];
uint16_t *reg16[8];
uint8_t *reg8[8];
struct emu_instruction instr;
struct emu_cpu_instruction_info *cpu_instr_info;
uint32_t last_fpu_instr[2];
char *instr_string;
bool repeat_current_instr;
struct emu_track_and_source *tracking;
};
instruction
struct emu_instruction
{
uint16_t prefixes;
uint8_t opcode;
uint8_t is_fpu : 1;
union
{
struct emu_cpu_instruction cpu;
struct emu_fpu_instruction fpu;
};
struct
{
struct emu_tracking_info init;
struct emu_tracking_info need;
} track;
struct
{
uint8_t has_cond_pos : 1;
uint32_t norm_pos;
uint32_t cond_pos;
} source;
};
fpu struct
union FpuMmxRegister {
long double fp;
unsigned char b[10]; //only use 8 of these for mmx
unsigned short s[4];
unsigned int i[2];
unsigned long long ll;
};
struct emu_fpu_instruction
{
uint16_t prefixes;
uint8_t fpu_opcode;
//uint8_t fpu_modrm;
struct /* mod r/m data */
{
union
{
uint8_t mod : 2;
uint8_t x : 2;
};
union
{
uint8_t reg1 : 3;
uint8_t opcode : 3;
uint8_t sreg3 : 3;
uint8_t y : 3;
};
union
{
uint8_t reg : 3;
uint8_t reg2 : 3;
uint8_t rm : 3;
uint8_t z : 3;
};
struct
{
uint8_t scale : 2;
uint8_t index : 3;
uint8_t base : 3;
} sib;
union
{
uint8_t s8;
uint16_t s16;
uint32_t s32;
} disp;
uint32_t ea;
} fpu_modrm;
//uint32_t ea;
uint16_t control;
uint16_t status;
uint16_t tag;
uint32_t lastIP;
uint32_t lastIPseg;
uint32_t lastDataPointer;
uint32_t lastDataSeg;
uint16_t opcode;
uint32_t last_instr;
union FpuMmxRegister r[8];
};
Tell me what I am doing wrong thank you
Just so you know they are all wrong in that starting function
src\fpu.c:17:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.control = 0x37F;
^
src\fpu.c:18:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.status = 0;
^
src\fpu.c:19:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.tag = 0xFFFF;
^
src\fpu.c:20:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.lastDataPointer = 0;
^
src\fpu.c:21:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.lastDataSeg = 0;
^
src\fpu.c:22:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.lastIP = 0;
^
src\fpu.c:23:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.lastIPseg = 0;
^
src\fpu.c:24:7: error: dereferencing pointer to incomplete type
cpu->instr.fpu.opcode = 0;
^
Your definition of struct emu_cpu is not visible at the point of definition of function fpuInit. For this reason all references to struct emu_cpu in fpuInit definition are seen as forward declarations of a new, incomplete type.
If your struct emu_cpu is defined in a header file, make sure it is included into the file that defines fpuInit.
Anonymous unions are only allowed at the end of a structure tree:
In
a->b.c.d =
d can be an anonymous ( without name ) struct or union,
b and c can't, and need to have names.
Reference: **Are "anonymous structs" standard? And, really, what *are* they? **
Say I have a C structure like:
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData; } tempStruct;
Is there a way to put all of those 3 members of the struct into a single 32-bit word, yet still be able to access them individually?
Something with the help of unions?
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData;
}
tempStruct;
typedef union {
tempStruct myStruct;
UINT32 myWord;
} stuff;
Or even better (with no "intermediate" struct):
#include <stdlib.h>
#include <stdio.h>
typedef union {
struct {
int nRow:8;
int nCol:8;
int nData:16;
};
int myWord;
} stuff;
int main(int args, char** argv){
stuff a;
a.myWord=0;
a.nCol=2;
printf("%d\n", a.myWord);
return 0;
}
What about just referring to it as a UINT32? It's not like C is type-safe.
tempStruct t;
t.nRow = 0x01;
t.nCol = 0x02;
t.nData = 0x04;
//put a reference to the struct as a pointer to a UINT32
UINT32* word = (UINT32 *) &t;
printf("%x", *word);
You can then get the value of the struct as a 32-bit word by dereferencing the pointer. The specifics of your system may matter, though...if I run this on my machine, the value of word is 0x00040201---that is, the fields are in reverse order. I don't think that's necessarily going to be the case if you're trying to serialize this to another system, so it's not portable.
If you want to actually store it as a 32-bit integer and then refer to the fields individually, why not
UINT32 word = 0x01020004;
and then somewhere else...
UINT8* row(UINT32 word) {
return (UINT8 *) &word + 3;
}
UINT8* col(UINT32 word) {
return ((UINT8 *) &word) + 2;
}
UINT16* data(UINT32 word) {
return ((UINT16 *) &word);
}
Macros will facilitate portable endianness.
Yes, you can use bit fields in C to do that. Something like:
typedef struct {
unsigned nRow : 8;
unsigned nCol : 8;
unsigned nData : 16;
} tempStruct;
If you want to control the memory layout also, you might want to take a look at #pragma pack. A non-portable option available on some compilers for this.
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
nRow will take only 8 bit and nCol will take 8 bit and nDate will take 16bit.
This will work for you.
I just wrote sample program to see the size of it
#include<stdio.h>
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
typedef struct {
int nRow;
int nCol;
int nData; } tempStructZ;
int main(void) {
printf("%d\n", sizeof(tempStruct));
printf("%d\n", sizeof(tempStructZ));
return 0;
}
Output:
4
16
Is there a clean way of casting a struct into an uint64_t or any other int, given that struct in <= to the sizeof int?
The only thing I can think of is only an 'ok' solution - to use unions. However I have never been fond of them.
Let me add a code snippet to clarify:
typedef struct {
uint8_t field: 5;
uint8_t field2: 4;
/* and so on... */
}some_struct_t;
some_struct_t some_struct;
//init struct here
uint32_t register;
Now how do i cast some_struct to capture its bits order in uint32_t register.
Hope that makes it a bit clearer.
I've just hit the same problem, and I solved it with a union like this:
typedef union {
struct {
uint8_t field: 5;
uint8_t field2: 4;
/* and so on... */
} fields;
uint32_t bits;
} some_struct_t;
/* cast from uint32_t x */
some_struct_t mystruct = { .bits = x };
/* cast to uint32_t */
uint32_t x = mystruct.bits;
HTH,
Alex
A non-portable solution:
struct smallst {
int a;
char b;
};
void make_uint64_t(struct smallst *ps, uint64_t *pi) {
memcpy(pi, ps, sizeof(struct smallst));
}
You may face problems if you, for example, pack the struct on a little-endian machine and unpack it on a big-endian machine.
you can use pointers and it will be easy
for example:
struct s {
int a:8;
int b:4;
int c:4;
int d:8;
int e:8; }* st;
st->b = 0x8;
st->c = 1;
int *struct_as_int = st;
hope it helps
You can cast object's pointer to desired type and then resolve it. I assume it can be a little bit slower than using unions or something else. But this does not require additional actions and can be used in place.
Short answer:
*(uint16_t *)&my_struct
Example:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t field1;
uint8_t field2;
} MyStruct;
int main() {
MyStruct my_struct = {0xFA, 0x7D};
uint16_t num_my_struct = *(uint16_t *)&my_struct;
printf("%X \n", num_my_struct); // 7DFA
return 0;
}