I've been trying to solve this problem for hours now. Although I found some similar questions, it just won't work.
I have a union within a struct. Now I want to initialize a const variable of this struct.
struct length
{
int minutes;
int seconds;
};
typedef struct article
{
char name[MAXLENGTH_A]
double price;
char type;
union size
{
int pages;
struct length blength;
} bsize
} art;
Now I want to initialize a const variable of this struct. I read somewhere that the following should work, but it doesn't. I always get the errors:
C2224: The operand to the left of '.pages' is not a class, structure, or union and
C2078: To many Initializers
const art book = {"Title", 24.99, NORMAL, { .pages = 50}};
I know that this example could be solved easier. But my real problem is, to initialize the 2nd element of the union, like this:
const art book = {"Title", 24.99, AUDIO, { .blength.seconds = 40}};
Neither the first, nor the second initialization is working.
Can someone tell me how do it right? I'm using C99 btw.
The { .pages = 50} construct is a designated initializer, a C99 feature unsupported by the MS C compiler (which is a C89 compiler, I'm told). This also restricts your ability to initialize unions only via their first member.
I can see these ways around this limitation: use { 50 } to initialize pages. Then forget the const and explicitly initialize .blength.seconds. The effects of const declaring objects are, uhm, overrated :-)
You need to initialise minutes and seconds
You don't need to explicitly specify member names
{"title",24.99,NORMAL,50,40}
Should sort your problem
Key is the members pages and length.minutes occupy the same memory space as its inside a union
Hope it helps
Related
#define LENGTH 6
typedef char data_t[LENGTH];
struct foo {
const data_t data;
...
}
...
void bar(data_t data) {
printf("%.6s\n", data);
struct foo myfoo = {*data};
printf("%.6s\n", foo.data);
}
I'm trying to have this struct which holds directly the data I'm interested in, sizeof(foo) == 6+the rest, not sizeof(foo) == sizeof(void*)+the rest. However I can't find a way to initialize a struct of type foo with a data_t. I think maybe I could remove the const modifier from the field and use memcpy but I like the extra safety and clarity.
I don't get any compile errors but when I run the code I get
123456
1??
so the copy didn't work properly I think.
This is for an arduino (or similar device) so I'm trying to keep it to very portable code.
Is it just not possible ?
EDIT: removing the const modifier on the data_t field doesn't seem to help.
It is possible to do this, for some cost >=0.
typedef struct
{
char c[LENGTH];
} data_t; // this struct is freely copyable
struct foo
{
const data_t data; // but this data member is not
int what;
};
void foo (char* x) {
data_t d; // declare freely copyable struct instance
memcpy(d.c, x, sizeof(d.c)); // memcpy it
struct foo foo = { d, 42 }; // initialise struct instance with const member
...
};
Some compilers (e.g. clang) are even able to optimise away the redundant copying (from x to d.c and then from d to foo.data ⇒ from x straight to foo.data). Others (gcc I'm looking at you) don't seem to be able to achieve this.
If you pass around pointers to data_t rather than straight char pointers, you won't need this additional memcpy step. OTOH in order to access the char array inside foo you need another level of member access (.data.c instead of just .data; this has no runtime cost though).
It's impossible to do it in a standard compliant way.
Due to its being const, const char data[6]; must be initialized to be usable, and it may only be initialized statically (static objects with no initializer get automatically zeroed), with a string literal, or with a brace-enclosed initializer list. You cannot initialize it with a pointer or another array.
If I were you, I would get rid of the const, document that .data shouldn't be changed post-initialization, and then use memcpy to initialize it.
(const on struct members doesn't work very well in my opinion. It effectively prevents you from being able to have initializer functions, and while C++ gets around the problem a little bit by having special language support for its constructor functions, the problem still remains if the const members are arrays).
I stumbled upon a very strange feature of C: you can declare a named structure inside another structure provided that declare a member variable of that type at the same time:
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st { /* <- named struct */
int capacity;
int load;
} battery;
};
The inner structure becomes then available outside the structure as any other type, rendering strange code like this perfectly valid:
struct Robot_st my_robot = {2, 3, {200, 50}};
struct BatteryStatus_st battery_snapshot; /* <- use of inner struct */
memcpy(
&battery_snapshot,
&my_robot.battery,
sizeof(struct BatteryStatus_st)
);
printf("robot position: %d,%d\n", my_robot.pos_x, my_robot.pos_y);
printf("battery load: %d%%\n", battery_snapshot.load);
Nesting unnamed structures feels right, because as you cannot access the type later, there is no confusion about the scope of the type. The above code is also not valid in C++, although the nested declaration is, because C++ understands it as a type in the namespace of the outer structure, so you need to access it using
struct Robot_st::BatteryStatus_st battery_snapshot;
which, despite feeling strange to declare both a type and a member at the same time, makes more sense.
So why is this construct valid in C? Is there any history/reason behind? Is there a use case for such a construct? (Mine was a mistake that led to failures, thus the question.)
Link to full working code.
Such constructs were allowed in C originally because structure names occupied a universe all their own which never had any sort of scoping rules applied to it [struct member names did too, by the way, which is why some of the structure types in older standard libraries have prefixes on their members]. Because some code exists which uses structure names in a fashion inconsistent with scoping, the standard could not be changed to prohibit such usage without breaking existing code. While there are times when it's worthwhile to break existing code (e.g. to rid C of the abomination called gets) this really isn't one of them.
In addition to the other two answers, here is a real usecase that calls for such a named inner struct:
struct LinkedList {
//data members stored once per list
struct LinkedListNode {
//data members for each entry of the list
struct LinkedListNode *next;
} *head, *tail;
};
Its hard to write a more concise definition for the structure of a linked list.
An unnamed inner struct won't do: The code that inserts something into the linked list will likely have to declare local variables with node pointers. And there is no point in declaring the node structure outside of the linked list structure.
Well, this is legal in C:
struct BatteryStatus_st {
int capacity;
int load;
};
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st battery;
};
and, as you pointed out, it is effectively identical to the code you posted (since C doesn't have the namespace/scoping rules introduced in C++).
If moving the "inner" type inside doesn't change anything, but may sometimes clarify intent, it would seem odd to prohibit it.
Let's say I have this structure:
struct OuterStruct
{
int a;
struct InnerStruct
{
int i;
int j;
} b;
} s;
Now I can access s.a, and I can even save it in a variable, to better handle it, pass it to functions, ...
int sa = s.a;
Well, now I want to do the same with s.b, and to do so I need InnerStruct to have a name!
???? sb = s.b; // here I have to use InnerStruct, otherwise sb would have no valid type!
The alternative would be to declare InnerStruct outside of OuterStruct, and then putting an instance of it inside as member of OuterStruct. But this would hide the fact that InnerStruct belongs to OuterStruct, making your intent less clear.
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.
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.
Why can't we initialize members inside a structure ?
example:
struct s {
int i = 10;
};
If you want to initialize non-static members in struct declaration:
In C++ (not C), structs are almost synonymous to classes and can have members initialized in the constructor.
struct s {
int i;
s(): i(10)
{
}
};
If you want to initialize an instance:
In C or C++:
struct s {
int i;
};
...
struct s s_instance = { 10 };
C99 also has a feature called designated initializers:
struct s {
int i;
};
...
struct s s_instance = {
.i = 10,
};
There is also a GNU C extension which is very similar to C99 designated initializers, but it's better to use something more portable:
struct s s_instance = {
i: 10,
};
The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is:
struct s { int i=10; };
This does not declare any variable - it defines a type. To declare a variable, you would add a name between the } and the ;, and then you would initialize it afterwards:
struct s { int i; } t = { 10 };
As Checkers noted, in C99, you can also use designated initializers (which is a wonderful improvement -- one day, C will catch up with the other features that Fortran 66 had for data initialization, primarily repeating initializers a specifiable number of times). With this simple structure, there is no benefit. If you have a structure with, say, 20 members and only needed to initialize one of them (say because you have a flag that indicates that the rest of the structure is, or is not, initialized), it is more useful:
struct s { int i; } t = { .i = 10 };
This notation can also be used to initialize unions, to choose which element of the union is initialized.
Note that in C++ 11, the following declaration is now allowed:
struct s {
int i = 10;
};
This is an old question, but it ranks high in Google and might as well be clarified.
Edit2: This answer was written in 2008 and relates to C++98. The rules for member initialization have changed in subsequent versions of the language.
Edit: The question was originally tagged c++ but the poster said it's regarding c so I re-tagged the question, I'm leaving the answer though...
In C++ a struct is just a class which defaults for public rather than private for members and inheritance.
C++ only allows static const integral members to be initialized inline, other members must be initialized in the constructor, or if the struct is a POD in an initialization list (when declaring the variable).
struct bad {
static int answer = 42; // Error! not const
const char* question = "what is life?"; // Error! not const or integral
};
struct good {
static const int answer = 42; // OK
const char* question;
good()
: question("what is life?") // initialization list
{ }
};
struct pod { // plain old data
int answer;
const char* question;
};
pod p = { 42, "what is life?" };
We can't initialize because when we declared any structure than actually what we do, just inform compiler about their presence i.e no memory allocated for that and if we initialize member with no memory for that. Normally what happens when we initialize any variable that depends on the place where we declared variable compiler allocate memory for that variable.
int a = 10;
if it's auto than in stack memory going to allocate
if it's global than in data sections memory going to allocate
So what memory is required to hold that data but in case of structure no memory is there so not possible to initialize it.
As you said it's just a member not a variable. When you declare a variable the compiler will also provide memory space for those variables where you can put values. In the case a of a struct member the compiler is not giving memory space for it, so you cannot assign values to struct members unless you create a variable of that struct type.