How to break struct members into bytes of a single word - c

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

Related

Automatic generation of struct printing function in C

I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}

Can a bit field structure be instantiated as an immediate?

Suppose I have the following (made up) definition:
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
I know I can use this to initialize a variable that gets passed to a function, such as :
color_t white = {.red = 0x7, .grn = 0x7, .blu = 0x3};
printf("color is %x\n", white.reg);
... but in standard C, is it possible to instantiate a color_t as an immediate for passing as an argument without assigning it first to a variable?
[I discovered that yes, it's possible, so I'm answering my own question. But I cannot promise that this is portable C.]
Yes, it's possible. And the syntax more or less what you'd expect. Here's a complete example:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
int main() {
// initializing a variable
color_t white = {.bits={.red=0x7, .grn=0x7, .blu=0x3}};
printf("color1 is %x\n", white.reg);
// passing as an immediate argument
printf("color2 is %x\n", (color_t){.bits={.red=0x7, .grn=0x7, .blu=0x3}}.reg);
return 0;
}

Is it possible to access the different Structure with same members by using Macros or any other functionality at runtime?(Structure updated))

In this code contains two structures and their naming is different. Structure member naming is same but type is different. Is there any possibility to change the structure name at run time by using macros or other functionality.
typedef struct STag_ABCRegisters
{
unsigned long aaa;
unsigned long bbb;
unsigned long ccc;
unsigned long dddd;
}RegistersABC;
typedef struct STag_CDERegisters
{
unsigned short aaa;
unsigned short bbb;
unsigned short ccc;
unsigned short dddd;
}RegistersCDE;
main()
{
int type = 1;
if(type == 1)
{
RegistersABC->ccc = 10;
}
else
{
RegistersCDE->ccc = 10;
}
/* after some process again checking the type updating structure*/
type = 2;
if(type == 1)
{
RegistersABC->aaa = 10;
}
else
{
RegistersCDE->aaa = 10;
}
}
I need the help for following process
In the above code contains complexity of if else condition.
So is there any possibilities for select the structure at run time??.
See the below Pseudo code steps for your understanding
main()
{
char type = "ABC";
Registers//type//->aaa = 10; // Type of structure name should be replaced here
}
As I stated in my comment, structures are just the way memory is organized on the machine.
If both structures were compiled by the same compiler on the same machine (architecture / OS), their memory footprint will be the same and you can simply cast their pointer to one to a pointer of the other.
This, however, is not the best way to go about "inheritance" with C.
At the moment, you can have something like this:
struct STag_ABCRegisters
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} RegistersABC;
struct STag_CDERegisters
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} RegistersCDE;
main()
{
(struct STag_CDERegisters*) pdata = (struct STag_CDERegisters*)&RegistersABC;
data->ccc = 10;
data->aaa = 10;
}
It works, but it isn't beautiful.
If you need two of the same, the correct way would be:
struct STag_Registers
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct STag_Registers RegistersABC, RegistersCDE;
main()
{
struct STag_Registers * data = &RegistersABC;
data->ccc = 10;
data->aaa = 10;
}
If you need struct inheritance, then the "trick" is to have the "parent" placed at the head of the struct, so that the memory footprint is aligned.
struct STag_Registers
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct STag_RegistersExtended
{
struct STag_Registers parent;
// ... more types
};
This allows a pointer to struct STag_RegistersExtended to be cast as a pointer to struct STag_Registers, so that functions that accept a pointer to struct STag_Registers can also accept a pointer to struct STag_RegistersExtended.
Good luck with C.
EDIT (answering comment)
If you're writing for an embedded system and you have reserved (fixed) memory addresses for the data, you could go with something such as:
typedef struct {
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} register_s;
#define PTR2REG(p) ((register_s *)(p))
#define REG_A PTR2REG(0x1000))
#define REG_B PTR2REG(0x9000))
inline void perform_work(register_s * reg)
{
reg->ccc = 10;
// ...
reg->aaa = 10;
}
main()
{
perform_work(REG_A);
perform_work(REG_B);
if(REG_A->aaa == 10) // should be true
printf("work was performed");
}
You should note that struct have a memory alignment and packing order. The compiler will add padding to the struct you defined in the question, due to the long's memory alignment requirements. You can read more about struct packing here.
If your embedded system requires an exact bit / byte match (and is free from padding requirements), you should tell the complier not to add any padding. This is often done using #pragma pack
EDIT 2
I'm not sure where the type in your question is derived from... but if you have a global variable with the address for the struct, you could go with:
typedef struct {
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} register_s;
#define PTR2REG(p) ((register_s *)(p))
#define REG_A PTR2REG(0x1000))
#define REG_B PTR2REG(0x9000))
register_s * active_register = REG_A;
inline void perform_work(void)
{
active_register->ccc = 10;
// ... active_register might change
active_register->aaa = 10;
}
main()
{
perform_work();
}
This is from a C++ perspective, you really should be more careful with those language tags if this is not what you want
Since C++ does not have reflection, it's not possible to do what you want at runtime. There are workarounds though.
For example one workaround could be to have a common base-class for the common elements (which in your simple example seems to be all). The you could have an unordered map translating strings to pointers to your structure.
Example:
struct CommonBase
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct ABC : CommonBase {};
struct DEF : CommonBase {};
int main()
{
std::unordered_map<std::string, std::unique_ptr<CommonBase>> items = {
{ "ABC", new ABC },
{ "DEF", new DEF }
};
std::cout << "Select item to modify (ABC or DEF): ";
std::string input;
std::cin >> input;
items[input]->aaa = 12;
}
For members that are not common, that are unique for each respective structure, then you need to actually check like you do now and then downcast the pointer to the correct type.
For a C solution there is none really, except to manually check like you do now.
Dynamic languages like python have buildin metadata table for reflection, so we just build one for help. Now it looks much like a script language.
_Generic need C11 std to work.
some code copied from How to save the result of typeof?
// some code copied from https://stackoverflow.com/questions/42222379/how-to-save-the-result-of-typeof
// gcc -std=c11 typeid_of_test.c
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
typedef struct STRU
{
int32_t aaa;
double bbb;
int ccc;
char dddd;
}STRU;
typedef struct Metainfo
{
int type;
char* name; //or hash
int offset;
}Metainfo;
enum {TYPE_UNKNOWN, TYPE_INT, TYPE_CHAR, TYPE_DOUBLE};
#define typeid_of(T) _Generic((T), int: TYPE_INT, long: TYPE_INT, char: TYPE_CHAR, double: TYPE_DOUBLE, default: 0)
#define META(ST_, M_) {typeid_of((__typeof__(((ST_ *)0)->M_))0), #ST_ "." #M_, offsetof(ST_, M_)}
/* { typeid, name, offset } */
Metainfo meta[]={
META(STRU, aaa),
META(STRU, bbb),
META(STRU, ccc),
META(STRU, dddd),
};
int set_by_name(char* member_name, char* value, void* p)
{
int offset=0, type=0;
for(int i=0; i<sizeof(meta)/sizeof(Metainfo); i++)
if(stricmp(member_name, meta[i].name)==0)
{
offset=meta[i].offset;
type = meta[i].type;
}
switch(type)
{
case TYPE_INT:
*(int*)((char*)p+offset) = atoi(value);
break;
case TYPE_CHAR:
*(char*)((char*)p+offset) = atoi(value);
break;
case TYPE_DOUBLE:
*(double*)((char*)p+offset) = atof(value);
break;
default:
return 0;
}
return 1;
}
int main(void)
{
for(int i=0; i<sizeof(meta)/sizeof(Metainfo); i++)
printf("type:%d, name: %s, offset: %d\n", meta[i].type, meta[i].name, meta[i].offset);
STRU b={0};
set_by_name("stru.bbb", "3.1415926", &b);
printf("stru.bbb == %f", b.bbb);
return 0;
}

Arrays in c shared library

I want to basically process a struct array in a method in a dynamic library, but when I pass the array and print it (in the exact same manner as in my main program) it has different values.
Consider a struct like this:
struct color {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
}
And the code to print it looks like this:
printf("pos: %p\n", array);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) array)[i]);
}
Now, what I'm doing in the test program is this:
printf("Table:\n");
print(table, size);
and the output looks like this (as excepted):
pos: 0x7fff5b359530
bgra: 00000000
bgra: ff0000ff
bgra: ff00ffff
But when i execute the same code in a function in the library this is what i get:
pos: 0x7fff5b359530
bgra: 00000008
bgra: 00000030
bgra: 5b3598e0
Now I'm wondering what I'm doing wrong, since i can't see a fault in my code. Also, the values must correlate somehow since, the output is always the same (Except for the address of course).
header.h
#include <stdint.h>
#ifndef __HEADER_H_
#define __HEADER_H_
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
void print(struct bmpt_color_bgra *table, uint8_t size);
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size);
#endif
library.c
#include <stdlib.h>
#include <stdio.h>
#include "header.h"
#define EXPORT __attribute__((visibility("default")))
__attribute__((constructor))
static void initializer(void) {
printf("[%s] initializer()\n", __FILE__);
}
__attribute__((destructor))
static void finalizer(void) {
printf("[%s] finalizer()\n", __FILE__);
}
EXPORT
void print(struct bmpt_color_bgra *table, uint8_t size) {
uint8_t i;
printf("pos: %p\n", table);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) table)[i]);
}
}
EXPORT
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size) {
printf("table in func:\n");
print(table, size);
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char **argv) {
struct bmpt_color_bgra arr[3];
struct bmpt_color_bgra c;
c.b = 0x0;
c.g = 0x0;
c.r = 0x0;
c.a = 0x0;
arr[0] = c;
c.b = 0xff;
c.a = 0xff;
arr[1] = c;
c.r = 0xff;
arr[2] = c;
//the first result (the correct one)
print(arr, 3);
//the second result
gen(arr, 3);
}
This probably comes down to memory alignment of the members within the struct, and the size of the struct itself differing between your program and the dynamic/shared library. You don't mention which compiler you are using, but using different compiler(s) or compiler options for your program and the shared library could cause this effect.
You can preserve binary compatibility between modules by specifying exactly how the members of the struct should be aligned. E.g in GCC you can force how the struct is represented in memory by use of an attribute.
See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html for GCC alignment instructions
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} __attribute__ ((packed));
Also take a look at Byte Alignment for integer (or other) types in a uint8_t array for a similar question.

Casting struct into int

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;
}

Resources