[SOLVED] Assigning variables to multiple fields in a structure is tiresome.
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
struct Foo
{
int x;
int y;
char* str;
};
struct Foo f1 = { 1, 2, "hello" }; // using this format, all values must be specified
/* or */
struct Foo f2 = { .y = 2, .str = "hello", .x = 1 }; // using this format, some fields may be omitted.
struct Foo f1 = { 1, 2, "hello" }; // using this format, all values must be specified
You can actually leave off initializers at the end with this, e.g. struct Foo f1 = { 1, 2 };, but not in the middle.
Quote:
Originally Posted by dwhitney67
Code:
struct Foo f2 = { .y = 2, .str = "hello", .x = 1 }; // using this format, some fields may be omitted.
I'd prefer using this method all the time, except it isn't allowed for C-struct initialization in C++. I generally use the y: 2 gcc extension; however, that doesn't respond well if the members are used out of order (it's really only good for clarity or skipping members in the middle somewhere.)
This is kind of a joke, but it certainly works using gcc statement expressions. Since you can only use {} to initialize (and not to assign) this is the lazy-man's way of copying members from multiple locations.
Humn... If these are the ways to assign a struct in C, then I think Pascal wins, with its 'with <struc_name> begin end' construct.
This isn't actually C; it's just something gcc allows. With the macros I think it's close to Pascal's. I've actually never used that in real code, though, nor do I plan to.
Not that I'm proposing this as a solution, but adding { and } to the macros makes it a competitor:
Code:
#define WITH(first) \
memcpy(&first, ({typeof(first) v = {
#define END(first) \
}; &v;}), sizeof(typeof(first)));
//...
struct Foo f1 = { 0, 0, "old string" };
//sometime later I want to change f1...
WITH(f1)
.y = 1,
.x = 2,
.str = "hello"
END(f1)
I'm proud of myself. This almost certainly won't compile on anything besides gcc.
Kevin Barry
are perfectly valid C99, and all three structures will contain the same values. The first two are compound literals, and the third one is a structure assignment. The structure will be assigned as an opaque block, not field-by-field; most compilers will use either memcpy() or open-coded equivalent.
For compiling C99 code (with all warnings, including pedantic ones) with GCC, I recommend using
Code:
gcc -std=c99 -Wall -pedantic ...
Outside interface declarations (header files) I could not care less about compatibility with C++, since C++ is a completely different language. They are related, yes, and you can compile most ANSI C and C89 code with a C++ compiler, but that's it.
I thought the thread had become a bit confusing, so I wrote my reply as a standalone post, not referring to any of the previous posts, for clarity.
For example, in your post you refer to, the use of memcpy() is utterly unnecessary.
Code:
(struct Foo)f1 = (struct Foo){ 1, 2, "Hello" };
behaves exactly the same way, including type-punning f1 if it happens to be some other (compatible) type, and is arguably much more readable C99. (If f1 is of struct Foo type, the first cast should of course be dropped. I only included it so that the statement is equivalent to the one you used.)
The latter form is also much easier for compilers to optimize. Taking the address of a variable usually means the compiler will not optimize it away, e.g. in registers. Although x86 is register-poor, in other architectures f1 might be entirely stored in registers; explicitly using memcpy() to assign it will force it to be stored in memory.
Quote:
Originally Posted by ta0kira
This is not valid C99:
Code:
struct foo {
float a;
long b;
int c;
char d;
};
int main()
{
struct foo f1, f2, f3;
f1 = ({
struct foo f4 = f2;
f4.a += f3.a;
f4.b -= f3.b;
f4;
});
}
Well, no, but why would you use something like that anyway? Assignment
is functionally equivalent, and valid C99, although you do need to name all fields (from f2). Assignments
Code:
f1 = f2;
f1.a += f3.a;
f1.b -= f3.b;
are also equivalent (and valid C99), but is the more typical pattern.
To the OP: readability is much more important than brevity. I personally use C99, especially compound literals in structure assignments. For partial assignments, I always use the last code sample above; that is, assign each field separately.
If you have a more complex structure in C99, with certain partial assignments done often, then it is a good idea to group those into substructures. You'll write less code that way, too. Here is an example:
Code:
struct point {
double x;
double y;
};
struct line {
struct point p1;
struct point p2;
};
/* Define a line with p1.x <= p2.x */
struct line define_line(struct point const p1, struct point const p2)
{
if (p1.x <= p2.x)
return (struct line){ .p1 = p1, .p2 = p2 };
else
return (struct line){ .p1 = p2, .p2 = p1 };
}
If you have even more complex assignments you do often, put them into separate functions, and mark the functions static inline . In C99, that means the function is local (not seen at all by other object files) and should be inlined. It is just as fast as writing a complex preprocessor macro to do it. (If not, blame the compiler; it really should be.)
I really hope I'm not just confusing the OP further,
I thought the thread had become a bit confusing, so I wrote my reply as a standalone post, not referring to any of the previous posts, for clarity.
For example, in your post you refer to, the use of memcpy() is utterly unnecessary.
Like I said in that other post, I wasn't proposing it as a solution and it's not something I've ever used in real code. Everything subsequent was just an effort to clear up confusion stemming from a satirical, yet technically valid, solution.
Kevin Barry
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.