Initialize C array with struct - c

Is it possible to initialise an array of uint8_t with a struct?
What I want to achieve is something similar to:
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) {
.address = 123,
.id = 456,
};
The reason I want to do this it to get an easy overlay view of the content I write to the byte array. I simply want an easy interface to whatever first bytes I need for the information that is displayed by the structure.
If thats not possible, what's the closest thing to it?

The standard way in C to overlay data types is by using unions:
#include <stdio.h>
#include <stdint.h>
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
union Memory {
uint8_t bytes[BIGGER_THAN_STRUCT];
struct Device devices[BIGGER_THAN_STRUCT/sizeof(struct Device)];
};
const union Memory memory = {
.devices = {
{ .address = 123, .id = 30 },
{ .address = 111, .id = 89 }
}
};
int main(void)
{
unsigned i;
for (i = 0; i < 16; i++)
printf("%d ", memory.bytes[i]);
putchar('\n');
return 0;
}
,
$ ./a
123 0 0 0 30 0 0 0 111 0 0 0 89 0 0 0

Beside approaching this via a union (as proposed by hdante here https://stackoverflow.com/a/27462808/694576) instead of trying:
const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) {
.address = 123,
.id = 456,
};
do quick and dirty:
uint8_t bytes[BIGGER_THAN_STRUCT] = {0};
*((struct Device *) bytes) = ((struct Device) {
.address = 123,
.id = 456,
});
or better do:
struct Device dev = {
.address = 123,
.id = 456,
};
uint8_t bytes[BIGGER_THAN_STRUCT] = {0};
...
size_t size_dev = sizeof dev;
memcpy(bytes, &dev, size_dev);
Then inspect array bytes up to the size_dev - 1th element.

This will do it then
static const uint8_t buffer[BIGGER_THAN_STRUCT] = {
0x7b, 0x00, 0x00, 0x00,
0xc8, 0x01, 0x00, 0x00
};

I think you maybe want to do something like that, even if the copy is not that necessary as b_sample is exactly what you need.
#include <stdio.h>
#include <stdint.h>
typedef struct Device dev;
struct Device {
uint32_t address;
uint32_t id;
};
int main(void) {
//create an instance `sample.address=123` and `sample.id=456`
dev sample = (dev) { 123, 456 };
//convert dev pointer to byte pointer, so you loop through bytes
uint8_t* b_sample = (uint8_t *)(&sample);
//buffer for copy
uint8_t* bytes[1024];
int size = (int)(sizeof(dev)/sizeof(uint8_t)), i;
for(i = 0; i < size; i++) {
bytes[i] = b_sample[i];
//see what values you copy
printf("%x ", bytes[i]);
}
return 0;
}
Demo: http://codepad.org/wE8dbBV1
If you want to divide the struct into uint16_t segments you can safely replace all uint8_t with uint16_t

Usually, when I have to work with bag of structured bytes, I create a "view" struct/class that gives me some higher-level interface to a block of memory. Manual pointer arithmetic is usually too error prone to be repeated. Create a "memory view" structure and unit-test it properly.
struct memory_view {
uint32_t *addr;
uint32_t *id;
};
void view_init(struct memory_view *view, void *buf, size_t bufsz) {
// TODO: validate buffer size using bufsz here
view->addr = (uint32_t*)buf;
view->id = (uint32_t*)(buf + sizeof(uint32_t));
}
struct memory_view view;
uint8_t buffer[LARGE_NUMBER];
view_init(&view, buffer, LARGE_NUMBER);
*view->addr = 0xDEADBEEF;
*view->id = 0xCAFEBABE;
You can see a similar technique in device drivers, when structures are initialized to access different hardware registers located in some memory region.
You could also get a buffer pointer, cast it to structure and try using this memory block as it were a structure. Doable, but memory alignment can bite you hard. Such code may or may not work, depending on compiler and system architecture.

Does this:
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
struct DeviceAndData {
struct Device d;
char filler[BIGGER_THAN_STRUCT - sizeof(Device)];
};
const struct DeviceAndData bytes_pre = { .d = { .address = 123, .id = 456 } };
const uint8_t* bytes = (uint8_t*)&bytes_pre;
do the trick? :)

There is an alternative to using a uint8_t byte[] array. You can also make use of a struct utilizing a bitfield for each addr and id. You (may/may not) find it more convenient, but it does provide an easy way to keep the offset information associated with any give addr/id pair.
I don't believe there is a way to directly make use of struct type Designated Initializers to fill the uint8_t byte array. I think the closest full initialization would be with memcpy. I've included that in the example below. Note, there is nothing that prevents you from filling the uint8_t byte array with memcpy, but then you have to track the offset within the uint8_t byte array to accurately point to any given byte in either addr or id for any given element. This is where the bitfield makes things a little easier. You get a one-to-one correlation between the struct Device index and the uibitfield index with a1..4 and b1..4 being the bytes within each addr and id, respectively.
A version using the uint8_t array is shown below this version.
Here is a short example with test data in an array of struct Device:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct /* bitfield corresponding to struct Device */
{
unsigned int a1 : 8,
a2 : 8,
a3 : 8,
a4 : 8;
unsigned int b1 : 8,
b2 : 8,
b3 : 8,
b4 : 8;
} uibitfield;
struct Device { /* original struct Device */
uint32_t addr;
uint32_t id;
};
int main () {
/* test data in an array of struct Device */
struct Device dev[] = { {0x4009f0, 0}, {0x4009f1, 1}, {0x4009f2, 2}, {0x4009f3, 3},
{0x4009f4, 4}, {0x4009f5, 5}, {0x4009f6, 6}, {0x4009f7, 7},
{0x4009f8, 8}, {0x4009f9, 9}, {0x4009fa, 10}, {0x4009fb, 11},
{0x4009fc, 12}, {0x4009fd, 13}, {0x4009fe, 14}, {0x4009ff, 15},
{0x400a00, 16}, {0x400a01, 17}, {0x400a02, 18}, {0x400a03, 19} };
int it = 0; /* general iterator */
size_t sz = sizeof (dev)/sizeof (*dev); /* size of array */
/* create validate and fill bitfield array */
uibitfield *bytes = calloc (sz, sizeof (*bytes));
if (!bytes) {
fprintf (stderr, "error: allocation failed.\n");
return 1;
}
memcpy (bytes, dev, sz * sizeof (dev));
/* print bytes in each addr & id in dev */
for (it = 0; it < sz; it++)
printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
it, (bytes + it)->a1, (bytes + it)->a2, (bytes + it)->a3, (bytes + it)->a4,
it, (bytes + it)->b1, (bytes + it)->b2, (bytes + it)->b3, (bytes + it)->b4);
printf ("\n");
return 0;
}
output:
$ ./bin/memview
addr[ 0]: 0xf0, 0x09, 0x40, 0x00
id[ 0]: 0x00, 0x00, 0x00, 0x00
addr[ 1]: 0xf1, 0x09, 0x40, 0x00
id[ 1]: 0x01, 0x00, 0x00, 0x00
addr[ 2]: 0xf2, 0x09, 0x40, 0x00
id[ 2]: 0x02, 0x00, 0x00, 0x00
addr[ 3]: 0xf3, 0x09, 0x40, 0x00
id[ 3]: 0x03, 0x00, 0x00, 0x00
addr[ 4]: 0xf4, 0x09, 0x40, 0x00
id[ 4]: 0x04, 0x00, 0x00, 0x00
(snip)
Note: it was a unclear how you would be using/filling struct Device and how much of an initial peek you wanted at the data in stuct Device, so this is just intended as an example of viewing the data.
using a uint8_t byte array:
If you do want to use the `uint8_t array, the changes needed are minimal:
/* using a uint8_t byte array */
uint8_t *bytearr = calloc (sz * 4, sizeof (*bytearr));
if (!bytearr) {
fprintf (stderr, "error: allocation failed.\n");
return 1;
}
memcpy (bytearr, dev, sz * sizeof (dev));
/* print bytes in each addr & id in dev using uint8_t array */
for (it = 0; it < sz * 4; it+=8)
printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
it, bytearr[it], bytearr[it+1], bytearr[it+2], bytearr[it+3],
it, bytearr[it+4], bytearr[it+5], bytearr[it+6], bytearr[it+7]);
output is the same

Related

Dynamically Populate Struct in C

Say you have a struct in C:
typedef struct ID_Info {
uint16_t model_number;
uint16_t serial_number;
uint16_t firmware_version;
} ;
ID_Info id_info;
Now, say I need to set each uint16 variable in this struct to the values of data received byte by byte. So for example, if I received the following bytes: 0x00, 0x11, 0x22, 0x33, 0x44 and 0x55 in some data array data[], I now need to set the values as follows:
id_info.model_number = data[1]*256 + data[0]; // 0x1100
id_info.serial_number = data[3]*256 + data[2]; // 0x3322;
id_info.firmware_version = data[5]*256 + data[4]; // 0x5544;
This is easy enough to hard code as shown above. However, I'd like to be able to do this without hard-coding values and iteratively if possible. Therefore, if I needed to add a variable to the struct, my code and loop would automatically know I need to iterate for two more bytes (assuming a unit16). So this loop would need to iterate foreach member in the struct. Furthermore, is there a way to infer the variable type to know how many bytes I need? Say I needed to add a uint8, and in this case the code could know I only need one byte.
So maybe the pseudo-code would look something like this:
int i = 0;
foreach(member in id_info)
if(member is uint8)
id_info.member = data[i];
i =+ 1;
else if (member is uint16)
id_info.member = data[i] + 256*data[i+1];
i =+ 2;
else
throw error
This way I could easily add and removed struct members without many changes to the code. Thanks in advance for any insight!
If it's not a performance issue (your sample data looks like it isn't), instead of a hard-coded structure with C types, you could define a structure where the type information is encoded, perhaps based on an enum, the name information as a string, and that along with a large enough value type.
The enum type might look like this:
typedef enum {
ui16, ui8
} Type;
One entry could be defined as:
struct entry {
Type type;
char *name;
long value;
};
It is assumed that long is large enough for the largest data type.
A small, self-contained C test program based on your example might then look like the following:
#include <stdio.h>
typedef enum {
ui16, ui8
} Type;
struct entry {
Type type;
char *name;
long value;
};
struct entry id_info[] = {
{ui16, "model_number", 0},
{ui16, "serial_number", 0},
{ui16, "firmware_version", 0}
};
int main(void) {
unsigned char data[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
int x = 0;
for (int i = 0; i < sizeof(id_info) / sizeof(id_info[0]); i++) {
struct entry *current = &id_info[i];
switch (current->type) {
case ui8:
current->value = data[x];
x++;
break;
case ui16:
current->value = data[x] + 256 * data[x + 1];
x += 2;
break;
}
}
//and now print it
for (int i = 0; i < sizeof(id_info) / sizeof(id_info[0]); i++) {
struct entry *current = &id_info[i];
switch (current->type) {
case ui8:
printf("uint8_t %s: %02lx\n", current->name, current->value);
break;
case ui16:
printf("uint16_t %s: %04lx\n", current->name, current->value);
break;
}
}
return 0;
}
The program would produce the following output on the debug console:
uint16_t model_number: 1100
uint16_t serial_number: 3322
uint16_t firmware_version: 5544
One way to do this is with preprocessor macros.
With this method, it is easy to add new elements. And, the import/export functions will be automatically updated.
#ifndef NOINC
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#endif
// define all struct members
#define ALLSTRUCT(_cmd) \
_cmd(uint16_t,"%u",model_number) \
_cmd(uint16_t,"%u",serial_number) \
_cmd(uint16_t,"%u",firmware_version)
// define symbol
#define SYMDEF(_typ,_fmt,_sym) \
_typ _sym;
// define struct
typedef struct ID_Info {
ALLSTRUCT(SYMDEF)
} ID_Info;
ID_Info id_info;
// deserialize
#define SYMIN(_typ,_fmt,_sym) \
do { \
str->_sym = *(_typ *) ptr; \
ptr += sizeof(_typ); \
} while (0);
// serialize
#define SYMOUT(_typ,_fmt,_sym) \
do { \
*(_typ *) ptr = str->_sym; \
ptr += sizeof(_typ); \
} while (0);
// print
#define SYMPRT(_typ,_fmt,_sym) \
printf(" " #_sym "=" _fmt " (%8.8X)\n",str->_sym,str->_sym);
// struct_out -- output struct to byte array
uint8_t *
struct_out(const ID_Info *str,uint8_t *ptr)
{
ALLSTRUCT(SYMOUT)
return ptr;
}
// struct_in -- input struct from byte array
const uint8_t *
struct_in(ID_Info *str,const uint8_t *ptr)
{
ALLSTRUCT(SYMIN)
return ptr;
}
// struct_prt -- print struct to byte array
void
struct_prt(const ID_Info *str)
{
printf("struct_prt:\n");
ALLSTRUCT(SYMPRT)
}
// prtu8 -- print byte array
void
prtu8(const uint8_t *ptr,size_t count,const char *sym)
{
printf("%s:",sym);
for (size_t idx = 0; idx < count; ++idx)
printf(" %2.2X",ptr[idx]);
printf("\n");
}
int
main(void)
{
uint8_t data_in[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
uint8_t data_out[sizeof(data_in)];
// show original byte array
prtu8(data_in,sizeof(data_in),"data_in");
// import data into struct
struct_in(&id_info,data_in);
// show struct values
struct_prt(&id_info);
// export data from struct
struct_out(&id_info,data_out);
// show exported byte array
prtu8(data_out,sizeof(data_out),"data_out");
// reimport the struct data
struct_in(&id_info,data_out);
// show struct data
struct_prt(&id_info);
return 0;
}
Here is the [redacted] preprocessor output:
typedef struct ID_Info {
uint16_t model_number;
uint16_t serial_number;
uint16_t firmware_version;
} ID_Info;
ID_Info id_info;
uint8_t *
struct_out(const ID_Info * str, uint8_t * ptr)
{
do {
*(uint16_t *) ptr = str->model_number;
ptr += sizeof(uint16_t);
} while (0);
do {
*(uint16_t *) ptr = str->serial_number;
ptr += sizeof(uint16_t);
} while (0);
do {
*(uint16_t *) ptr = str->firmware_version;
ptr += sizeof(uint16_t);
} while (0);
return ptr;
}
const uint8_t *
struct_in(ID_Info * str, const uint8_t * ptr)
{
do {
str->model_number = *(uint16_t *) ptr;
ptr += sizeof(uint16_t);
} while (0);
do {
str->serial_number = *(uint16_t *) ptr;
ptr += sizeof(uint16_t);
} while (0);
do {
str->firmware_version = *(uint16_t *) ptr;
ptr += sizeof(uint16_t);
} while (0);
return ptr;
}
void
struct_prt(const ID_Info * str)
{
printf("struct_prt:\n");
printf(" " "model_number" "=" "%u" " (%8.8X)\n", str->model_number, str->model_number);
printf(" " "serial_number" "=" "%u" " (%8.8X)\n", str->serial_number, str->serial_number);
printf(" " "firmware_version" "=" "%u" " (%8.8X)\n", str->firmware_version, str->firmware_version);
}
void
prtu8(const uint8_t * ptr, size_t count, const char *sym)
{
printf("%s:", sym);
for (size_t idx = 0; idx < count; ++idx)
printf(" %2.2X", ptr[idx]);
printf("\n");
}
int
main(void)
{
uint8_t data_in[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
uint8_t data_out[sizeof(data_in)];
prtu8(data_in, sizeof(data_in), "data_in");
struct_in(&id_info, data_in);
struct_prt(&id_info);
struct_out(&id_info, data_out);
prtu8(data_out, sizeof(data_out), "data_out");
struct_in(&id_info, data_out);
struct_prt(&id_info);
return 0;
}
Here is the test program output:
data_in: 00 11 22 33 44 55
struct_prt:
model_number=4352 (00001100)
serial_number=13090 (00003322)
firmware_version=21828 (00005544)
data_out: 00 11 22 33 44 55
struct_prt:
model_number=4352 (00001100)
serial_number=13090 (00003322)
firmware_version=21828 (00005544)

Attempting to allocate a union to a void* in a struct

The goal is to create a structure that contains 3 fields. One of those fields needs to be a uint32_t union but the flags will be different for each element. I believe the best way to do this is to create a separate union for each peripheral and assign it to a void pointer in the parent struct (somehow).
The Current Plan:
//--------------Register for AAA
typedef union
{
struct
{
uint32_t spare : 32; //< Bits 0-31 not used
}Bits;
uint32_t FullData;
}ABC_EMPTY_DATA;
ABC_EMPTY_DATA AAA_Data;
//--------------Register for BBB
typedef union
{
struct
{
uint32_t use32BitColor : 1; //< Bit0
uint32_t enableTimer : 1; //< Bit1
uint32_t fooTheBar : 1; //< Bit2
uint32_t spare : 29; //< Bits 3-31 not used
}Bits;
uint32_t FullData;
}ABC_BBB_DATA;
ABC_EMPTY_DATA BBB_Data;
//--------------Register for CCC
typedef union
{
struct
{
uint32_t useInternalFrameTick : 1; //< Bit0
uint32_t useExternalFrameTick : 1; //< Bit1
uint32_t spare : 30; //< Bits 2-31 not used
}Bits;
uint32_t FullData;
}ABC_CCC_DATA;
ABC_CCC_DATA CCC_Data;
//-------The Peripherals with register element
typedef struct
{
char *Name;
unsigned int HexCmd;
void *Data; //Connect to corasponding XXXX_Data
}ABC_dataStructs;
//----- Initializing Peripherals
typedef struct
{
ABC_dataStructs AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = (void*) &AAA_Data};
ABC_dataStructs BBB = {.Name = "BBB", .HexCmd = 0x00, .Data = (void*) &BBB_Data};
ABC_dataStructs CCC = {.Name = "CCC", .HexCmd = 0x00, .Data = (void*) &CCC_Data};
}ABC_CommandList;
void main(){
ABC_CommandList everything;
everything.CCC.FullData = 0x000F;
everything.BBB.use32BitColor = 0;
int myint = everything.AAA.HexCmd;
}
Currently, I am having initializeing the values within the struct
ABC_dataStructs AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = (void*) &AAA_Data};
is invalid
Also and more importantly the assigning of the union is not working as intended. The current result only allows for everything.AAA.Data without being able to assign/read individual bits.
I also tried to explain the intent of the SW in order to avoid an "XY problem" and if I am approaching this wrong or you think of something better let me know. Thank You.
Note: C struct, union pointer to struct has another approach of putting structs in the unions instead of unions to the structs, but it doesn't help with my main issue of assigning these to a void*
The problem you're having with the initialization is that you're defining a type and attempting to initialize it as if it's a variable at the same time. You need to first define the struct, then initialize an instance of it:
typedef struct
{
ABC_dataStructs AAA;
ABC_dataStructs BBB;
ABC_dataStructs CCC;
}ABC_CommandList;
void main(){
ABC_CommandList everything = {
.AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = &AAA_Data},
.BBB = {.Name = "BBB", .HexCmd = 0x00, .Data = &BBB_Data},
.CCC = {.Name = "CCC", .HexCmd = 0x00, .Data = &CCC_Data},
};
...
Note also that it's not required to cast to/from a void *.
Then the problem here:
everything.CCC.FullData = 0x000F;
everything.BBB.use32BitColor = 0;
Is that CCC and BBB are of type ABC_dataStructs, and that type does not have fields named FullData or use32BitColor. You would need to cast the Data member to the proper pointer type, then dereference that:
((ABC_CCC_DATA *)everything.CCC.Data)->FullData = 0x000F;
((ABC_BBB_DATA *)everything.BBB.Data)->use32BitColor = 0;
All that being said, there's a better way of modeling this data. What you really want is a union of the 3 register types. Then ABC_dataStructs would contain that union along with a separate field which flags which union to use.
typedef struct
{
uint32_t spare : 32; //< Bits 0-31 not used
} ABC_EMPTY_DATA;
typedef struct
{
uint32_t use32BitColor : 1; //< Bit0
uint32_t enableTimer : 1; //< Bit1
uint32_t fooTheBar : 1; //< Bit2
uint32_t spare : 29; //< Bits 3-31 not used
} ABC_BBB_DATA;
typedef struct
{
uint32_t useInternalFrameTick : 1; //< Bit0
uint32_t useExternalFrameTick : 1; //< Bit1
uint32_t spare : 30; //< Bits 2-31 not used
} ABC_CCC_DATA;
typedef struct
{
char *Name;
unsigned int HexCmd;
union {
ABC_EMPTY_DATA AAA;
ABC_BBB_DATA BBB;
ABC_CCC_DATA CCC;
uint32_t FullData;
};
}ABC_dataStructs;
Then you can define the following:
ABC_CommandList everything = {
.AAA = {.Name = "AAA", .HexCmd = 0x00, .AAA = {}},
.BBB = {.Name = "BBB", .HexCmd = 0x00, .BBB = { .use32BitColor = 0 }},
.CCC = {.Name = "CCC", .HexCmd = 0x00, .FullData = 0x000F },
};

Using C++ variadic templates to initialize variable-length arrays in static structs

I've been writing some code that deals with USB at the packet level. One "hangup" I've run into is that with USB, you have some structs that contain arrays of other structs (not pointers):
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} PACKED endp_descriptor_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
endp_descriptor_t endpoints[];
} PACKED int_descriptor_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
int_descriptor_t interfaces[];
} PACKED cfg_descriptor_t;
The cfg_descriptor_t contains zero or more int_descriptor_ts, and each int_descriptor_t contains zero or more endp_descriptor_ts.
I'm working on a microcontroller with fairly limited space (256K flash, 64K RAM), so I wanted to avoid dynamic allocation as much as possible and define these structs at compile time:
static cfg_descriptor_t cfg_descriptor = {
.bLength = 9,
.bDescriptorType = 2, //config descriptor
.wTotalLength = 18,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80, //bus powered, no remote wakeup
.bMaxPower = 250, //x2 = 500mA (maximum allowed by spec)
.interfaces = {
{
.bLength = 9,
.bDescriptorType = 4, //interface
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = 0xFF,
.bInterfaceSubClass = 0x0,
.bInterfaceProtocol = 0x0,
.iInterface = 0,
.endpoints = {
{
.bLength = 7,
.bDescriptorType = 5, //endpoint
.bEndpointAddress = 0x81,
.bmAttributes = 0x03,
.wMaxPacketSize = 64,
.bInterval = 10,
}
}
}
}
};
Unfortunately, it seems gcc doesn't understand what I'm trying to do here, and complains about too many initializers for β€˜int_descriptor_t [0]’ - i.e. it apparently can't determine the length of the array from the initializers. (Maybe I've just made some simple mistake here?)
I thought I might take advantage of C++11's variadic templates for this:
template<typename... interfaces>
struct PACKED x_cfg_descriptor_t {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
interfaces...;
};
but this doesn't work either: expected unqualified-id before β€˜...’ token on the interfaces... line.
I've seen some examples of variable-sized tuples using variadic templates, but I couldn't quite understand what they were doing, and they suggested that the actual layout in memory would be in reverse order of the template parameters. (I think recursive templates are involved...)
So the question is: can I define a static struct instance with a variable number of members at compile time?
Well, I didn't exactly answer the question, but I found a much better method: move the arrays out of the structs, and define one large struct:
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} PACKED endp_descriptor_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
//endp_descriptor_t endpoints[];
} PACKED int_descriptor_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
//int_descriptor_t interfaces[];
} PACKED cfg_descriptor_t;
static struct {
cfg_descriptor_t cfg;
int_descriptor_t iface[1];
endp_descriptor_t endp[1];
} PACKED cfg_descriptor = {
.cfg = {
.bLength = 9,
.bDescriptorType = 2, //config descriptor
.wTotalLength = 18,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80, //bus powered, no remote wakeup
.bMaxPower = 250, //x2 = 500mA (maximum allowed by spec)
},
.iface = {
{ //iface[0]
.bLength = 9,
.bDescriptorType = 4, //interface
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = 0xFF,
.bInterfaceSubClass = 0x0,
.bInterfaceProtocol = 0x0,
.iInterface = 0,
},
},
.endp = {
{ //endp[0]
.bLength = 7,
.bDescriptorType = 5, //endpoint
.bEndpointAddress = 0x81,
.bmAttributes = 0x03,
.wMaxPacketSize = 64,
.bInterval = 10,
}
}
};
Using PACKED (which expands to __attribute__((__packed__))) ensures the memory layout is still what USB expects, and this allows to define any number of endpoints and interfaces per configuration descriptor. The downside is that I don't see a way to have this in an external file, besides defining a typedef struct for every configuration descriptor (and having to update it in two different places) or exporting it as a void* (and being unable to address individual fields).
This doesn't really answer the question about whether variadic templates can be used for this purpose, though...

How to generate a file from C-hexvalues?

I have a C-array that looks like this:
char hexc[] = {
0x41, 0x80, 0x7a, 0x39, 0xea, 0x7e, 0x27, 0xfc,
0xe6, 0x45, 0x9c, 0x8b, 0xb5, 0xce, 0xa7, 0x35,
0x5f, 0xf2, 0x43, 0xcf, 0x89, 0xd8, 0x61, 0xec,
0xe7, 0xed, 0x2e, 0x34, 0x45, 0x0c, 0x32, 0xae,
0x71, 0x4f, 0x1c, 0xd8, 0xb5, 0x8c, 0x1e, 0xdd,
0x5d, 0x90, 0xf3, 0xf2, 0xe7, 0xa6, 0x4f, 0xef,
0xec, 0x96, 0xe3, 0xca, 0x8e, 0xeb, 0x64, 0x1d,
0x18, 0xa9, 0x95, 0xec, 0x64, 0x02, 0xf8, 0x26,
};
I knew that behind this hex-representations is a .GIF-file, what is the best way to generate from this hex-values a viewable file again? And how to add the missing GIF-header?
You would just open the file and write to it:
FILE *f = fopen("filename.gif", "wb");
if (!f) return; // or do something else
fwrite(hexc, 1, sizeof(hexc), f);
fclose(f);
Make sure to #include <stdio.h>.
open the file as binary
ofstream outfile ("new.gif",ofstream::binary);
and then write your buffer
outfile.write (hexc, sizeof hexc);
Turbo C DOS code
/****************************************************************************
** This support Compuserve 256 colour GIF87a and GIF89a image up to **
** 320x200 in size. **
****************************************************************************/
//This program requires a stack of at least 19.5K!!
#include "stdio.h"
typedef
struct GIFHeader {
char Signature [7];
unsigned int ScreenWidth, ScreenHeight;
unsigned char Depth, Background, Zero;
};
struct GIFDescriptor {
char Separator;
unsigned int ImageLeft, ImageTop, ImageWidth, ImageHeight;
unsigned char Depth;
};
char far *Screen = (char far *)0xA0000000L;
//For loading from the file
FILE *GIFFile;
unsigned int BPointer;
unsigned char Buffer [257];
//GIF data is stored in blocks of a certain size
unsigned char BlockSize;
//For loading the code
unsigned char CodeSize;
char BitsIn;
unsigned char Temp;
//Coordinates
unsigned int X, Y, tlX, tlY, brX, brY;
//The string table
unsigned int Prefix [4096];
unsigned char Suffix [4096];
//This sets the display to VGA 320x200 in 256 colours
void VGAScreen ()
{
asm {
mov ax, 0x13
int 0x10
}
}
//This resets the display to text mode
void TextScreen ()
{
asm {
mov ax, 0x3
int 0x10
}
}
//This sets a DAC register to a specific Red Green Blue-value
void SetDAC(unsigned char DAC, unsigned char R, unsigned char G, unsigned char B)
{
outportb (0x3C8, DAC);
outportb (0x3C9, R);
outportb (0x3C9, G);
outportb (0x3C9, B);
}
//This sets one pixel on the screen
void PutPixel (unsigned int x, unsigned int y, unsigned char c)
{
Screen [(y << 8) + (y << 6) + x] = c;
}
//Function to read from the buffer
unsigned char LoadByte ()
{
//Read next block}
if (BPointer == BlockSize) {
fread (Buffer, BlockSize + 1, 1, GIFFile);
BPointer = 0;
}
//Return byte
return Buffer [BPointer++];
}
//Procedure to read the next code from the file
unsigned int ReadCode ()
{
int Counter;
unsigned int Code;
Code = 0;
//Read the code, bit by bit
for (Counter = 0; Counter < CodeSize; Counter++) {
//Maybe, a new byte needs to be loaded with a further 8 bits
if (++BitsIn == 9) {
Temp = LoadByte ();
BitsIn = 1;
}
//Add the current bit to the code
if (Temp & 1) Code += 1 << Counter;
Temp >>= 1;
}
return Code;
}
//Procedure to draw a pixel
void NextPixel (unsigned int c)
{
//Actually draw the pixel on screen
PutPixel (X, Y, c & 255);
//Move to next row, if necessary
if (++X == brX) {
X = tlX;
Y++;
}
}
//Local function to output a string. Returns the first character.
unsigned char OutString (unsigned int CurCode)
{
unsigned int OutCount;
unsigned char OutCode [1024];
//If it's a single character, output that
if (CurCode < 256) {
NextPixel (CurCode);
} else {
OutCount = 0;
//Store the string, which ends up in reverse order
do {
OutCode [OutCount++] = Suffix [CurCode];
CurCode = Prefix [CurCode];
} while (CurCode > 255);
//Add the last character
OutCode [OutCount++] = CurCode;
//Output all the string, in the correct order
do {
NextPixel (OutCode [--OutCount]);
} while (OutCount);
}
//Return 1st character
return CurCode;
}
//This actually loads the GIF
void LoadGIF (char *Filename)
{
//For loading from the GIF file
struct GIFHeader Header;
struct GIFDescriptor Descriptor;
//Colour information
unsigned char BitsPerPixel,
NumOfColours;
unsigned int DAC;
unsigned char Palette [256][3];
//For indexing the string table
unsigned int FirstFree, FreeCode;
//All the code information
unsigned char InitCodeSize;
unsigned int Code, OldCode, MaxCode;
//Special codes
unsigned int ClearCode, EOICode;
//Check whether the GIF file exists, and open it
GIFFile = fopen (Filename, "rb");
if (GIFFile == 0) {
TextScreen ();
printf ("Could not open file %s", Filename);
return;
}
//Read header
fread (&Header, 6, 1, GIFFile);
Header.Signature [6] = 0;
fread (&Header.ScreenWidth, sizeof (Header) - 7, 1, GIFFile);
//Check signature and terminator
if ((strcmp (Header.Signature, "GIF87a")
&& strcmp (Header.Signature, "GIF89a"))
|| Header.Zero) {
TextScreen ();
printf ("Not a valid GIF file\n");
return;
}
//Get amount of colours in image
BitsPerPixel = 1 + (Header.Depth & 7);
NumOfColours = (1 << BitsPerPixel) - 1;
//Load global colour map
fread (Palette, 3, (NumOfColours + 1), GIFFile);
for (DAC = 0; DAC <= NumOfColours; DAC++)
SetDAC (DAC, Palette [DAC][0] >> 2,
Palette [DAC][1] >> 2,
Palette [DAC][2] >> 2);
//Load the image descriptor
fread (&Descriptor, sizeof (Descriptor), 1, GIFFile);
if (Descriptor.Separator != ',') {
TextScreen ();
printf ("Incorrect image descriptor.\n");
return;
}
//Get image corner coordinates
tlX = Descriptor.ImageLeft;
tlY = Descriptor.ImageTop;
brX = tlX + Descriptor.ImageWidth;
brY = tlY + Descriptor.ImageHeight;
//Some restrictions apply
if (Descriptor.Depth & 128) {
TextScreen ();
printf ("Local colour maps not supported\n");
return;
}
if (Descriptor.Depth & 64) {
TextScreen ();
printf ("Interlaced images not supported\n");
return;
}
//Get initial code size
fread (&CodeSize, 1, 1, GIFFile);
//GIF data is stored in blocks, so it's necessary to know the size
fread (&BlockSize, 1, 1, GIFFile);
//Start loader
BPointer = BlockSize;
//Special codes used in the GIF spec
ClearCode = 1 << CodeSize; //Code to reset
EOICode = ClearCode + 1; //End of file
//Initialize the string table
FirstFree = ClearCode + 2; //Strings start here
FreeCode = FirstFree; //Strings can be added here
//Initial size of the code and its maximum value
InitCodeSize = ++CodeSize;
MaxCode = 1 << CodeSize;
BitsIn = 8;
//Start at top left of image
X = Descriptor.ImageLeft;
Y = Descriptor.ImageTop;
do {
//Read next code
Code = ReadCode ();
//If it's an End-Of-Information code, stop processing
if (Code == EOICode) break;
//If it's a clear code...
else if (Code == ClearCode) {
//Clear the string table
FreeCode = FirstFree;
//Set the code size to initial values
CodeSize = InitCodeSize;
MaxCode = 1 << CodeSize;
//The next code may be read
Code = ReadCode ();
OldCode = Code;
//Set pixel
NextPixel (Code);
//Other codes
} else {
/*If the code is already in the string table, it's string is displayed,
and the old string followed by the new string's first character is
added to the string table.*/
if (Code < FreeCode)
Suffix [FreeCode] = OutString (Code);
else {
/*If it is not already in the string table, the old string followed by
the old string's first character is added to the string table and
displayed.*/
Suffix [FreeCode] = OutString (OldCode);
NextPixel (Suffix [FreeCode]);
}
//Finish adding to string table
Prefix [FreeCode++] = OldCode;
//If the code size needs to be adjusted, do so
if (FreeCode >= MaxCode && CodeSize < 12) {
CodeSize++;
MaxCode <<= 1;
}
//The current code is now old
OldCode = Code;
}
} while (Code != EOICode);
//Close the GIF file
fclose (GIFFile);
}
void main (int argcount, char *argvalue[])
{
char FileName [80];
//Check if a filename was passed as a parameter, otherwise ask for one
if (argcount > 1) {
strcpy (FileName, argvalue [1]);
} else {
printf ("Enter filename:");
gets (FileName);
}
//Switch to graphics screen
VGAScreen ();
//Load GIF file
LoadGIF (FileName);
//Wait for keypress
getch ();
//Switch back to text mode
TextScreen ();
}

How can I define an arbitrarily-sized 2D array and then determine its dimensions at compile-time?

Executive summary:
How can I define an arbitrarily-sized 2D array in C?
How can I determine the dimensions of that array at compile-time?
Full disclosure:
I'm writing code for an embedded controller. My application requires several lookup tables with different sizes which will all be used by one lookup function (a binary search). Here is what I have so far:
typedef struct
{
unsigned char count; // number of rows in the table
unsigned char width; // number of bytes in each row
const unsigned char * data; // pointer to table data[count][width]
}
LookupTable;
// returns the index of a value from within a table
unsigned char Lookup(unsigned long value, const LookupTable * table);
This part is working. What I would like to do now is define these tables in my source without having to manually enter the count and width constants. Here is what I am doing now:
#define T1_count 100
#define T1_width 3
const unsigned char table1_data[T1_count][T1_width] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
...
};
const LookupTable table1 = { T1_count, T1_width, table1_data };
Here is what I would like to be able to do (pseudo-code, since this array definition will not actually compile):
const unsigned char table1_data[] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
...
};
const LookupTable table1 =
{
get_count_expr(table1_data),
get_width_expr(table1_data),
table1_data
};
Obviously, get_count_expr and get_width_expr would have to be constant expressions of some sort, based on the size of the table, and not actual function calls.
To be clear, no part of this design is cast in stone. I'm just posting what I have so far, in the hopes that my intent is clear. Any ideas for improvement would be appreciated.
The "why":
These tables will be changed often, and it would make maintenance easier if entries could be added and removed, or the width of a table changed without having to manually adjust the constants each time. Having to keep track of the sizes manually can be error-prone and violates DRY. I'm looking for a better way.
Hmmm ... you can leave the leftmost size to the compiler:
#define T1_WIDTH 3
const unsigned char table1_data[][T1_WIDTH] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
/* ... */
};
T1_count = sizeof table1_data / sizeof *table1_data;
T1_width = sizeof *table1_data;
Well, it's ugly as hell, but I think the only way to do it within the constraints you've listed is to include the data in a string, and than have initialization code parse the string and generate the table. Ideally you'd do that in a script rather than use C to do it, but if it has to be in C, it has to be in C..
Note that in no way do I claim the following to be production code, but it's just a proof of concept...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define datatable "\
{ 0x12, 0x34, 0x56 },\
{ 0x14, 0x36, 0x10 },\
{ 0x13, 0x37, 0x11 },\
{ 0x12, 0x38, 0x12 }"
typedef struct
{
unsigned char count; // number of rows in the table
unsigned char width; // number of bytes in each row
unsigned char **data; // pointer to table data[count][width]
}
LookupTable;
int parsedatatable(char *data, LookupTable **table) {
char *p, *sp, save;
unsigned char *tabledata;
int count = 0, width = 0;
unsigned int tmp;
int i,j;
/* find count */
p = strstr(data,"{");
while (p) {
p++;
p = strstr(p, "{");
count++;
}
/* find width */
p = strstr(data, "{");
p++;
sp = strstr(p, "}");
if (sp != NULL) {
save = *sp;
*sp = '\0';
}
while (p) {
p = strstr(p, ",");
width++;
if (p != NULL) p++;
}
if (sp != NULL) {
*sp = save;
}
printf("Count = %d, width = %d\n",count, width);
tabledata = (unsigned char *)malloc(width*count*sizeof(unsigned char));
*table = (LookupTable *)malloc(sizeof(LookupTable));
(*table)->data = (unsigned char **)malloc(count*sizeof(unsigned char*));
for (i=0; i<count; i++) {
(*table)->data[i] = &(tabledata[i*width]);
}
(*table)->count = count;
(*table)->width = width;
p = data;
for (i=0; i<count; i++) {
p = strstr(p,"{");
if (!p) {
fprintf(stderr,"Fail (a) reading in data!: %s\n",data);
free((*table)->data);
free(tabledata);
free(*table);
return -1;
}
p++;
for (j=0; j<width; j++) {
printf("Scanning <%s>, ",p);
sscanf(p,"%x",&tmp);
printf("got %d\n",tmp);
(*table)->data[i][j] = tmp;
p = strstr(p,",");
if (!p && j<width-1) {
fprintf(stderr,"Fail (b) reading in data!: %d, %d, %s\n",i,j,data);
free((*table)->data);
free(tabledata);
free(*table);
return -1;
}
p++;
}
}
return 0;
}
void printtable(LookupTable *table) {
unsigned char i,j;
for (i=0; i<table->count; i++) {
printf("{");
for (j=0; j<table->width; j++) {
printf("%x ",table->data[i][j]);
}
printf("}\n");
}
return;
}
int main(int argc, char **argv) {
char *data;
LookupTable *table;
data = (char *)malloc(strlen(datatable)+1);
strcpy(data,datatable);
parsedatatable(data,&table);
printtable(table);
return 0;
}
Well, but who fills these tables with data? I think that generated sources are better solution.
Define table1_data inside a header. You can auto-generate that header using a script. I do something similar to that for some of my projects. I have a CSV file with data and a Ruby or Python script that generates a header from it.

Resources