Problems with arrays of unspecified lengths - c

I'm writing an IrDA stack in c and implementing the Information Access Service component and i need a lookup table for class/key/value pairs. To keep it in an orderly format, I'm trying to put it all into one initialiser. the following code works just fine and compiles the data to compact linked tables in ROM.
#define IAS_PTYPE_STRING 0x00
#define IAS_PTYPE_BYTE 0x01
typedef struct {
UBYTE* name;
UBYTE type;
UBYTE* value;
} IAS_Attrib_t ;
typedef IAS_Attrib_t* IAS_Attrib_List_t[];
typedef struct {
UBYTE* name;
IAS_Attrib_List_t* attributes;
} IAS_Class_t;
static const IAS_Class_t IAS_Database[] = {
{"IrDA:IrCOMM",
&(IAS_Attrib_List_t){
&(IAS_Attrib_t){"Parameters", IAS_PTYPE_STRING, "IrDA:TinyTP:LsapSel"},
NULL,
},
},
};
However I'm having trouble getting the data back out. according to the types used, i should be able to do something like this:
UBYTE class = 1;
UBYTE attr = 1;
UBYTE* name = (*(IAS_Database[class].attributes))[attr]->name;
this is because
IAS_Database[class].attributes is type IAS_Attrib_List_t*
*(IAS_Database[class].attributes) is type IAS_Attrib_List_t i.e. IAS_Attrib_t*[]
(*(IAS_Database[class].attributes))[attr] should be type IAS_Attrib_t*
(*(IAS_Database[class].attributes))[attr]->name should be type UBYTE*
however when i try to query the table, i get invalid use of array with unspecified bounds back from mspgcc. Even a hack like (IAS_Attrib_t*)((IAS_Database[class].attributes)+(sizeof(IAS_Attrib_t)*attr)) fails until i cast the db to void like (IAS_Attrib_t*)((void*)(IAS_Database[class].attributes)+(sizeof(IAS_Attrib_t)*attr)) however this just feels so dirty. I'd really like to figure out the correct syntax to do it the right way.

Never mind.
In my utter frustration it seems i tried every variant bar the one I put up here. (*(IAS_Database[class].attributes))[attr] does indeed work properly and even works when expressed as (*IAS_Database[class].attributes)[attr] i believe the compiler was incorrectly assuming that the first pointer (being to a UBYTE**) was actually a list and was trying to apply the index to a pointer type (where the type is incomplete).

typedef IAS_Attrib_t* IAS_Attrib_List_t[];
why are you using these brackets ? use a number inside or remove them

Related

How to use a generic struct via cast to access multiple structs with the same 1st element

Given that there are multiple struct typedefs (all different) but with the same first element 'out' as in:
typedef struct myStructOneOfMany
{
uint8_t out;
//somestuff that is different
void* inPntr[33];
struct myStructOneOfMany *prev;
struct myStructOneOfMany *next;
}myStructOneOfMany;
how could one use a generic struct:
typedef struct OUT
{
uint8_t out;
}OUT;
with only the 1st element to access just the 1st element of all the different types?
assume:
myStructOneOfMany *currMyStructOneOfMany = //pointer to 1st in the linked list
I have tried:
uint8_t value = (struct OUT*)(currMyStructOneOfMany->inPntr[4])->out;
... along with other variations and I get nowhere.
Thanks!
EDIT:
As written in Jonathan Leffler's great comment - C11 §6.7.2.1 ¶15 says:
A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa.
Which is why we either use a struct in the first element (matching padding and all), or a single variable / enum. I prefer using structs because they are easier to extend later on, if you want to add something.
Structs are interesting and complex animals, their field include compiler specific paddings and alignments.
Although very often the code will work fine by a simple matching of the top element, it isn't always the case when you're trying to use a common header with a number of fields (that would be undefined behavior due to padding concerns)... single elements are fine.
A classic way (that is also a compiler correct way) to implement "inheritance" in C would look something like this:
struct parent_s {
/* common attributes */
int object_type; /* for example */
};
struct child_s {
/* must be first element if you want pointers to be interchangeable. */
struct parent_s parent;
/*more stuff */
int my_unique_data;
}
Similar code is used in network address structures.
P.S.
This was a very quick and simplified answer, enough to get you started but not very accurate.
As you explore this you will discover techniques that allow you to place the common structures all over the place and have multiple inheritance when you need it.
I used to miss inheritance in C, but these days I love C better than many OO languages because it gives me more control over the memory structure and I can manage most inheritance features without the need to resort to virtual function tables (which I very rarely do).
EDIT:
Following #AjayBrahmakshatriya 's comment, I thought a quick casting example might be nice... So here's something I'm working on that uses the exact type of inheritance you're asking about (I just started this part of the code today, so it might be glitchy, I also didn't sleep for two days...):
/** Used to identify te type of the RESP object. */
enum resp_type_enum {
/** A String object (`resp_string_s`) that indicates an error. */
RESP_ERR = 0,
/** A simple flag object object (`resp_object_s`) for NULL. */
RESP_NULL,
/** A simple flag object object (`resp_object_s`) for OK. */
RESP_OK,
/** A Number object object (`resp_number_s`). */
RESP_NUMBER,
/** A String object (`resp_string_s`). */
RESP_STRING,
/** An Array object object (`resp_array_s`). */
RESP_ARRAY,
/** A specific Array object object (`resp_array_s`) for Pub/Sub semantics. */
RESP_PUBSUB,
};
/* This is the parent "class" / object */
typedef struct { enum resp_type_enum type; } resp_object_s;
/* an Array child class */
typedef struct {
enum resp_type_enum type;
size_t len;
size_t pos; /** allows simple iteration. */
resp_object_s *array[];
} resp_array_s;
/* a String child class */
typedef struct {
enum resp_type_enum type;
size_t len;
uint8_t string[];
} resp_string_s;
/* a Number child class */
typedef struct {
enum resp_type_enum type;
int64_t number;
} resp_number_s;
I wrote macros that allow me to easily cast from one type to another. They include error checks (by returning NULL if the types don't match:
#define resp_obj2arr(obj) \
((resp_array_s *)((obj)->type == RESP_ARRAY || (obj)->type == RESP_PUBSUB \
? (obj) \
: NULL))
#define resp_obj2str(obj) \
((resp_string_s *)((obj)->type == RESP_STRING || (obj)->type == RESP_ERR \
? (obj) \
: NULL))
#define resp_obj2num(obj) \
((resp_number_s *)((obj)->type == RESP_NUMBER ? (obj) : NULL))
This allows me to do use the macros to easily switch between the different "types".
switch (obj->type) {
case RESP_ERR:
safe_write1('-');
safe_write2((resp_obj2str(obj)->string), (resp_obj2str(obj)->len));
safe_write_eol();
break;
case RESP_NULL:
safe_write2("$-1\r\n", (resp_obj2str(obj)->len));
break;
case RESP_OK:
safe_write2("+OK\r\n", 5);
case RESP_ARRAY:
case RESP_PUBSUB:
safe_write1('*');
safe_write_i(resp_obj2arr(obj)->len);
safe_write_eol();
{
resp_array_s *a = resp_obj2arr(obj);
a->pos = a->len;
obj = NULL;
while (a->pos) {
a->pos--;
push_obj(a->array[a->pos], obj);
obj = a->array[a->pos];
}
}
// ...
}
Well it seems I over thought things.
The last comment above compiles and works !
uint8_t value = *(uint8_t *)(…some expression denoting a pointer to a structure with a uint8_t first member…);
I thought I had to make a generic struct similar to my several typedefs.
As Jonathan said ... no need to get fancy.
The pointer to the struct is also a pointer to the first element as long as you cast the pointer to point to the same type as the first element.
Thanks to Jonathan Leffler for pointing this out !!
PS: one thing that threw me was the additional * at the beginning.
I assumed the cast to (uint8_t*) was enough but I guess this just says "treat the right side after the cast as a pointer to type uint8_t.
Without the * before the cast ... 'value' would get the pointer value ... not the value that the pointer points to.
I am still between beginner and intermediate on C but making progress
Thanks to you all !!

Data encapsulation in C

I am currently working on an embedded system and I have a component on a board which appears two times. I would like to have one .c and one .h file for the component.
I have the following code:
typedef struct {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
} ads1248_options_t;
Those are all hardware settings. I create two instances of this struct (one for each part).
Now I need to keep an array of values in the background. E.g. I can read values from that device every second and I want to keep the last 100 values. I would like this data to be non-accessible from the "outside" of my component (only through special functions in my component).
I am unsure on how to proceed here. Do I really need to make the array part of my struct? What I thought of would be to do the following:
int32_t *adc_values; // <-- Add this to struct
int32_t *adc_value_buffer = malloc(sizeof(int32_t) * 100); // <-- Call in initialize function, this will never be freed on purpose
Yet, I will then be able to access my int32_t pointer from everywhere in my code (also from outside my component) which I do not like.
Is this the only way to do it? Do you know of a better way?
Thanks.
For the specific case of writing hardware drivers for a microcontroller, which this appears to be, please consider doing like this.
Otherwise, use opaque/incomplete type. You'd be surprised to learn how shockingly few C programmers there are who know how to actually implement 100% private encapsulation of custom types. This is why there's some persistent myth about C lacking the OO feature known as private encapsulation. This myth originates from lack of C knowledge and nothing else.
This is how it goes:
ads1248.h
typedef struct ads1248_options_t ads1248_options_t; // incomplete/opaque type
ads1248_options_t* ads1248_init (parameters); // a "constructor"
void ads1248_destroy (ads1248_options_t* ads); // a "destructor"
ads1248.c
#include "ads1248.h"
struct ads1248_options_t {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
};
ads1248_options_t* ads1248_init (parameters)
{
ads1248_options_t* ads = malloc(sizeof(ads1248_options_t));
// do things with ads based on parameters
return ads;
}
void ads1248_destroy (ads1248_options_t* ads)
{
free(ads);
}
main.c
#include "ads1248.h"
int main()
{
ads1248_options_t* ads = ads1248_init(parameters);
...
ads1248_destroy(ads);
}
Now the code in main cannot access any of the struct members, all members are 100% private. It can only create a pointer to a struct object, not an instance of it. Works exactly like abstract base classes in C++, if you are familiar with that. The only difference is that you'll have to call the init/destroy functions manually, rather than using true constructors/destructors.
It's common that structures in C are defined completely in the header, although they're totally opaque (FILE, for example), or only have some of their fields specified in the documentation.
C lacks private to prevent accidental access, but I consider this a minor problem: If a field isn't mentioned in the spec, why should someone try to access it? Have you ever accidentally accessed a member of a FILE? (It's probably better not to do things like having a published member foo and a non-published fooo which can easily be accessed by a small typo.) Some use conventions like giving them "unusual" names, for example, having a trailing underscore on private members.
Another way is the PIMPL idiom: Forward-declare the structure as an incomplete type and provide the complete declaration in the implementation file only. This may complicate debugging, and may have performance penalties due to less possibilities for inlining and an additional indirection, though this may be solvable with link-time optimization. A combination of both is also possible, declaring the public fields in the header along with a pointer to an incomplete structure type holding the private fields.
I would like this data to be non-accessible from the "outside" of my
component (only through special functions in my component).
You can do it in this way (a big malloc including the data):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
} ads1248_options_t;
void fn(ads1248_options_t *x)
{
int32_t *values = (int32_t *)(x + 1);
/* values are not accesible via a member of the struct */
values[0] = 10;
printf("%d\n", values[0]);
}
int main(void)
{
ads1248_options_t *x = malloc(sizeof(*x) + (sizeof(int32_t) * 100));
fn(x);
free(x);
return 0;
}
You could make a portion of your structure private like this.
object.h
struct object_public {
uint32_t public_item1;
uint32_t public_item2;
};
object.c
struct object {
struct object_public public;
uint32_t private_item1;
uint32_t *private_ptr;
}
A pointer to an object can be cast to a pointer to object_public because object_public is the first item in struct object. So the code outside of object.c will reference the object through a pointer to object_public. While the code within object.c references the object through a pointer to object. Only the code within object.c will know about the private members.
The program should not define or allocate an instance object_public because that instance won't have the private stuff appended to it.
The technique of including a struct as the first item in another struct is really a way for implementing single inheritance in C. I don't recall ever using it like this for encapsulation. But I thought I would throw the idea out there.
You can:
Make your whole ads1248_options_t an opaque type (as already discussed in other answers)
Make just the adc_values member an opaque type, like:
// in the header(.h)
typedef struct adc_values adc_values_t;
// in the code (.c)
struct adc_values {
int32_t *values;
};
Have a static array of array of values "parallel" to your ads1248_options_t and provide functions to access them. Like:
// in the header (.h)
int32_t get_adc_value(int id, int value_idx);
// in the code (.c)
static int32_t values[MAX_ADS][MAX_VALUES];
// or
static int32_t *values[MAX_ADS]; // malloc()-ate members somewhere
int32_t get_adc_value(int id, int value_idx) {
return values[id][value_idx]
}
If the user doesn't know the index to use, keep an index (id) in your ads1248_options_t.
Instead of a static array, you may provide some other way of allocating the value arrays "in parallel", but, again, need a way to identify which array belongs to which ADC, where its id is the simplest solution.

What is the purpose of creating a struct with only one field

On the project in my company I saw a couple of times people creating a struct that contains only one element.
the latest one is added, in this example ipAddr is another struct( a good explanation to the case when ipAddr is an array is given by 'Frerich Raabe' but unfortunately thats not the case here)
typedef struct
{
ipAddr ip;
} Record;
I guess if the code is changing and in its beginning this makes sense since more fields can be easily added and the code can be easily manipulated to support the new fields, but this is a project started a long time ago written according to a design so I dont think its the issue here.
Why would one create a struct of one field then?
I can think of a couple reasons:
In case more fields may be needed later. This is somewhat common.
To deliberately make the outer type incompatible with the inner type.
For an example of the second, imagine this:
typedef struct
{
char postal_code[12];
} Destination;
In this case, the Destination is fully specified by the postal code, yet this will let us define functions like this:
int deliver(const char* message, const Destination* to);
This way, no user can inadvertently call the function with the two arguments reversed, which they could easily do if they were both plain strings.
A common reason for a struct with just one field is that the single field is an array, and you'd like to be able to define functions returning such array values. Consider e.g.
typedef unsigned char ipAddr[4];
void f(ipAddr ip); /* OK */
ipAddr g(void); /* Compiler barfs: cannot return array. */
This can be resolved by introducing a struct with a single member of type ipAddr:
typedef unsigned char ipAddr[4];
typedef struct {
ipAddr ip;
} Record;
void f(Record ip); /* OK */
Record g(void); /* Also OK: structs can be returned by value. */
However, even passing arrays to functions is problematic: you don't actually pass the array, you pass a pointer (the type "decays" into a pointer). Imagine f declared above would need to create a copy of the given IP address:
typedef unsignd char ipAddr[4];
void f(ipAddr ip) {
ipAddr *a = malloc(sizeof(ip));
/* ... */
}
This only happens to work with 32bit builds because the size of a pointer is the same (4 bytes) as the size of an array of four unsigned char values. A 64bit build (or a differently sized array) would exhibit a bug, either allocating too much or too little memory. This happens because inside f, ip is of type unsigned char *, i.e.a pointer. A struct helps with this, since it doesn't decay.

memcpy Inheritance-like structs - is it safe?

I have two structs I'm working with, and they are defined nearly identical. These are defined in header files that I cannot modify.
typedef struct
{
uint32_t property1;
uint32_t property2;
} CarV1;
typedef struct
{
uint32_t property1;
uint32_t property2;
/* V2 specific properties */
uint32_t property3;
uint32_t property4;
} CarV2;
In my code, I initialize the V2 struct at the top of my file, to cover all my bases:
static const carV2 my_car = {
.property1 = value,
.property2 = value,
/* V2 specific properties */
.property3 = value,
.property4 = value
};
Later, I want to retrieve the values I have initialized and copy them into the struct to be returned from a function via void pointer. I sometimes want V2 properties of the car, and sometimes V1. How can I memcpy safely without having duplicate definitions/initializations? I'm fairly new to C, and its my understanding that this is ugly and engineers to follow me in looking at this code will not approve. What's a clean way to do this?
int get_properties(void *returned_car){
int version = get_version();
switch (version){
case V1:
{
CarV1 *car = returned_car;
memcpy(car, &my_car, sizeof(CarV1)); // is this safe? What's a better way?
}
case V2:
{
CarV2 *car = returned_car;
memcpy(car, &my_car, sizeof(CarV2));
}
}
}
Yes, it's definitely possible to do what you're asking.
You can use a base struct member to implement inheritance, like this:
typedef struct
{
uint32_t property1;
uint32_t property2;
} CarV1;
typedef struct
{
CarV1 base;
/* V2 specific properties */
uint32_t property3;
uint32_t property4;
} CarV2;
In this case, you're eliminating the duplicate definitions. Of course, on a variable of type CarV2*, you can't reference the fields of the base directly - you'll have to do a small redirection, like this:
cv2p->base.property1 = 0;
To upcast to CarV1*, do this:
CarV1* cv1p = &(cv2p->base);
c1vp->property1 = 0;
You've written memcpy(&car, &my_car, sizeof(CarV1)). This looks like a mistake, because it's copying the data of the pointer variable (that is, the address of your struct, instead of the struct itself). Since car is already a pointer (CarV1*) and I'm assuming that so is my_car, you probably wanted to do this instead:
memcpy(car, my_car, sizeof(CarV1));
If my_car is CarV2* and car is CarV1* (or vice versa), then the above code is guaranteed to work by the C standard, because the first member of a struct is always at a zero offset and, therefore, the memory layout of those two for the first sizeof(CarV1) bytes will be identical.
The compiler is not allowed to align/pad that part differently (which I assume is what you meant about optimizing), because you've explicitly declared the first part of CarV2 to be a CarV1.
Since in your case you are stuck with identically defined structs that you can't change, you may find useful that the C standard defines a macro/special form called offsetof.
To be absolutely sure about your memory layouts, I'd advise that you put a series of checks during the initialization phase of your program that verifies whether the offsetof(struct CarV1, property1) is equal to offsetof(struct CarV2, property1) etc for all common properties:
void validateAlignment(void)
{
if (offsetof(CarV1, property1) != offsetof(CarV2, property1)) exit(-1);
if (offsetof(CarV1, property2) != offsetof(CarV2, property2)) exit(-1);
// and so on
}
This will stop the program for going ahead in case the compiler has done anything creative with the padding.
It also won't slow down your program's initialization because offsetof is actually calculated at compile time. So, with all the optimizations in place, the void validateAlignment(void) function should be optimized out completely (because a static analysis would show that the exit conditions are always false).
What you wrote will almost work, except that instead of memcpy(&car, ... you should just have memcpy (car, ..., but there is no reason to use memcpy in such a case. Rather, you should just copy each of the fields in a separate statement.
car->property1 = my_car.property1
(is my_car a pointer or not? it's impossible to tell from the code fragment)
For the second case, I think you can just assign the entire struct: *car = my_car
there is no perfect solution but one way is to use a union
typedef union car_union
{
CarV1 v1;
CarV2 v2;
} Car;
that way the size will not differ when you do a memcpy - if version v1 then v2 specific parts will not be initialized.
In C and Objective-C, this is fine in practice. (In theory, the compiler must see the declaration of a union containing both structs as members).
In C++ (and Objective-C++), the language very carefully describes when this is safe and when it isn't. For example, if you start with
typedef struct {
public:
...
then the compiler is free to re-arrange where struct members are. If the struct uses no C++ features then you are safe.

Can you Enumerate Through Values in a Struct?

I know that when defining a an enum you can enumerate through the list numerically:
typedef enum MONTH { Jan = 1, Feb, March, ... };
Can you enumerate through values in a struct the same way? I basically want to loop through the values in a struct using a for or while loop.
struct items {char *item_name, int item_value};
struct items Items_list[] =
{
"item 1", 2000,
"item 2", 3600,
....
};
Language used is C.
Edit: I may have just answered my own question since what I had in mind is an array of structs. Will leave the question up for now however.
This declaration and initializer combination are invalid. (The question changed while the original version of this answer was written.)
If you are asking "is there a way to access the first member of the structure, then the second, without knowing the structure element names", then the answer is 'no, not without careful encoding beforehand'.
The careful coding involves multiple steps. For each element, you need an encoding of the type, the offset of the member in the structure, and perhaps the size of the member (if the encoding of the type does not give that to you anyway):
typedef enum { MT_INT, MT_CHAR_PTR, ... } MemberType;
typedef struct MemberAccess
{
const char *name;
size_t offset;
MemberType type;
} MemberAccess;
static const MemberAccess members[] =
{
"item_name", offsetof(struct items, item_name), MT_CHAR_PTR },
"item_value", offsetof(struct items, item_value), MT_INT },
};
And now, with excruciating care, you can write code to either get or set the value in the Nth member of a struct item pointed at by a particular pointer. However, doing so is still far from trivial.
int get_int(const void *data, const MemberAccess *member)
{
assert(member->type == MT_INT);
return (*(const int *)((const char *)data + member->offset));
}
GCC notwithstanding, you need the cast to a character pointer; you cannot legitimately do pointer arithmetic on void *.
You might then invoke:
int value = get_int(&Items_list[1], &members[1]);
to get at the integer value of the second field of the second element of the array.
This is so excruciating to deal with that there have to be excellent reasons to go through the overhead. There can be such reasons. I know of a system with 400 configuration parameters (which is a problem in its own right, but lets pretend that's OK; they've accumulated over 20 years of development) stored in a structure with heterogeneous types for the members. The code that manipulates it is written out 400 times - ouch! - because it doesn't use a system driven off an analogue of the MemberAccess structure. The code would be a lot more compact than it currently is because there are about a dozen data types to deal with, so most of the code is repetitive. Another way of reducing the complexity of that code would be to make everything into a string, but there are issues with that transformation too.
No, you cannot iterate the elements of a struct. The best you can do is hardcode the names of the struct in the loop:
struct items *item = Items_list;
while (item < Items_list + sizeof(Items_list) / sizeof(*Items_list)) {
printf("%s %d", item->item_name, item->item_value);
++item;
}
Also note that you cannot reliably iterate an enum either, because it could be defined like this:
typedef enum MONTH { Jan = 1, Feb = 13, March = 10, ... };
And the elements are both out of order and non-continuous (i.e. there are gaps in the numbers).
One way to do this, when you have a pointer type in the inner struct, and when that pointer cannot be meaningfully NULL, is to do something like:
for (int i=0; Item_List[i].item_name != 0; i++) {
// do whatever
}
If you don't have a handy pointer type, a "sentinel" value can often be used to mark the last record.
You'll need to remember to add a null element/sentinel at the end of your structure array though, and fix your syntax.
No, there's no easy way to do this. A struct is not a numerical value, so you can't loop through its values/members. You can either use an array instead of a struct and access its memebers with a simple for loop, or write a special enumerator callback function which takes the struct as its one argument, a number as another argument, and using case or if statements, looks up each member of the structure.

Resources