I have this structure representing a generic message
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint8_t *data;
} generic_msg_t;
After reading type1 and type 2 I can know to which specific message it corresponds, for example this one:
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint16_t a;
uint8_t b;
uint8_t c;
double d;
double e;
double f;
double g;
double h;
uint8_t i;
} specific_msg_t;
Supposing msg contains verified data, I would like to understand why if I do this I can not access to d, e, f, g, h data (but well a, b, c)
specific_msg_t * specific_msg = (specific_msg_t *) msg;
uint16_t a = specific_msg->a; //OK
double d = specific_msg->d; //NOK`
I have to do instead:
unsigned char * buffer = (unsigned char *) msg;
double d = buffer[15] + (buffer[14] << 8) + (buffer[13] << 16) + (buffer[12] << 24) + (buffer[11] << 32) + (buffer[10] << 40) + (buffer[9] << 48) + (buffer[8] << 56);`
specific_msg_t has potentially different alignment requirements than generic_msg_t so on some architectures, that code could result in a crash - the compiler has no particular requirement to align a generic_msg_t object on a boundary suitable for accessing a double.
It would help to know exactly what error you're getting though.
As long as the sender and receiver use the same headers (uint16_t is the same for both of them) and both of them use the same architecture (e.g. x86 or whatever) there shouldn't be too many problems.
I would also define a union with all the specific message types that you need, in order to avoid those nasty calculations and most of the casts.
Something similar to this:
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
// whatever you need here...
double a;
float b;
// etc.
} specific_msg_t1;
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint16_t a;
uint8_t b;
uint8_t c;
double d;
double e;
double f;
double g;
double h;
uint8_t i;
} specific_msg_t2;
typedef struct
{
uint16_t length;
uint8_t type1;
uint8_t type2;
} selector_msg_t;
typedef union
{
selector_msg_t selector;
specific_msg_t1 msgtype1;
specific_msg_t2 msgtype2;
} message_type_t;
With this setup you could be sending messages of type "message_type_t". Use the member "selector" to decide which specific type of message you received and then use the appropriate specific type to read the different data members.
If the size difference is considerable between the specific types, then it is a bad idea, but if you're not limited by bandwidth then it's at least readable and not that error prone.
Related
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? **
The C struct:
typedef struct {
int32_t tid;
int32_t pos;
uint32_t bin:16, qual:8, l_qname:8;
uint32_t flag:16, n_cigar:16;
int32_t l_qseq;
int32_t mtid;
int32_t mpos;
int32_t isize;
} bam1_core_t;
typedef struct {
bam1_core_t core;
int l_data, m_data;
uint8_t *data;
uint64_t id;
} bam1_t;
The Julia data type I write:
type BinQualLqname
bin::UInt16
qual::UInt8
l_qname::UInt8
end
type FlagNCigar
flag::UInt16
n_cigar::UInt16
end
type Bam1_core_t
tid::Int32
pos::Int32
bin_qual_lqname::BinQualLqname
flag_ncigar::FlagNCigar
l_qseq::Int32
mtid::Int32
mpos::Int32
isize::Int32
end
type Bam1_t
core::Ptr{Bam1_core_t}
l_data::Int32
m_data::Int32
data::Ptr{Cuchar}
id::UInt64
end
When I used above Datatype Bam1_t in julia function:
function sam_read1!(samfile,bamheader,b::Ptr{Bam1_t})
record = ccall((:sam_read1,"libhts"),Cint, (Ptr{Void},Ptr{Void},Ptr{Bam1_t}),samfile,bamheader,b)
end
The data in b modified by sam_read1! is nonsense. How can I debug this? Is there any tools or tips recommended?
sam_read1
int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b);
where
typedef struct {
bam1_core_t core;
int l_aux, data_len, m_data;
uint8_t *data;
} bam1_t;
Seems to be different than your Bam1_t. Would
type Bam1_t
core::Bam1_core_t
l_aux::Int32
data_len::Int32
m_data::Int32
data::Ptr{Cuchar}
end
work?
So i have 2 structs:
struct cmd {
uint8_t a;
uint8_t b;
uint8_t c;
};
typedef struct someName{
uint8_t size;
struct cmd cmdID;
} someName_t;
And i got a char res[0] containing the string "0xabc".
This 0xabc need to be put inside the cmd struct.
But the problem is 0xabc is 12 bit (1010 1011 1100) so if i put this into the struct with only uint8_t a and uint8_t b it will work because it will "fit" into 16 bits. But i got uint8_t a, uint8_t b and uint8_t c so 24 bits and that is my problem..
I tried:
someName_t msg;
sscanf(res[0], "0x%x", &(msg.cmdID));
But this does not work. This does work however if i remove the uint8_t c variable from the struct because it then fits inside the remaining 16 bits..
So how can i get the value "0xabc" into this (24bit) struct without adjusting the struct.
If you have control of your input format, i.e. you can guarantee it will always be something like 0xabc, then you can try:
const char input[] = "0xabc";
uint32_t tmp;
sscanf(input, "0x%x", &tmp);
struct cmd cmdid;
cmdid.a = (tmp & 0xFF0000U) >> 16;
cmdid.b = (tmp & 0xFF00U) >> 8;
cmdid.c = (tmp & 0xFFU);
You could try changing struct cmd to:
struct cmd {
unsigned int c:4;
unsigned int b:4;
unsigned int a:4;
};
But YMMV depending on compiler. Works OK on MSVC++ 2010.
I'm trying to create an application that inverts the colors of a bitmap file but am having some trouble with actually gathering the data and from the bitmap. I'm using structures to keep the data for the bitmap and it's header. Right now I have:
struct
{
uint16_t type;
uint32_t size;
uint32_t offset;
uint32_t header_size;
int32_t width;
int32_t height;
uint16_t planes;
uint16_t bits;
uint32_t compression;
uint32_t imagesize;
int32_t xresolution;
int32_t yresolution;
uint32_t ncolours;
uint32_t importantcolours;
} header_bmp
struct {
header_bmp header;
int data_size;
int width;
int height;
int bytes_per_pixel;
char *data;
} image_bmp;
Now for actually reading and writing the bitmap I have the following:
image_bmp* startImage(FILE* fp)
{
header_bmp* bmp_h = (struct header_bmp*)malloc(sizeof(struct header_bmp));
ReadHeader(fp, bmp_h, 54);
}
void ReadHeader(FILE* fp, char* header, int dataSize)
{
fread(header, dataSize, 1, fp);
}
From here how do I extract the header information into my header structure?
Also if anyone has any good resources over reading and writing bitmaps, please let me know. I have been searching for hours and can't find much useful information over the topic.
You actually should already have all the data in the correct places. The only issue possibly gone wrong could be endianness. e.g. is the number 256 represented in "short" as
0x01 0x00 or 0x00 0x01.
EDIT: there is something wrong related to the syntax of struct...
struct name_of_definition { int a; int b; short c; short d; };
struct name_of_def_2 { struct name_of_definition instance; int a; int b; }
*ptr_to_instance; // or one can directly allocate the instance it self by
// by omitting the * mark.
struct { int b; int c; } instance_of_anonymous_struct;
ptr_to_instance = malloc(sizeof(struct name_of_def_2));
also:
ReadHeader(fp, (char*)&ptr_to_instance->header, sizeof(struct definition));
// ^ don't forget to cast to the type accepted by ReadHeader
In this way you can directly read data into the middle of the struct, but the possible issue of endianness still lurks around.
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;
}