473,486 Members | 2,277 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Surprising struct initialization

I suppose you can never know C++ fully. I would have never guessed
this actually compiles and works:

struct Point { int x, y; };

struct Line
{
Point endpoint[2];
int weight;
};

Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}

Both gcc and Visual Studio 2005 compile that happily.

My question would be: Is that *really* correct, or are both compilers
simply being lenient? What are the exact rules for the initialization
blocks of structs?
Jul 3 '08 #1
10 5029
Juha Nieminen wrote:
I suppose you can never know C++ fully. I would have never guessed
this actually compiles and works:

struct Point { int x, y; };

struct Line
{
Point endpoint[2];
int weight;
};

Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}

Both gcc and Visual Studio 2005 compile that happily.

My question would be: Is that *really* correct, or are both compilers
simply being lenient? What are the exact rules for the initialization
blocks of structs?
IIRC, if a struct (or an abused class) is a POD, you can aggregate its
construction using classic C notation. POD is Plain Ole' Data - no virtuals,
constants, etc. A POD has an implementation-defined memory layout - and strict
top-to-bottom member locations - so the {,,,} can exploit this to unambiguously
drop data into each slot.

--
Phlip
Jul 3 '08 #2
Juha Nieminen <no****@thanks.invalidkirjutas:
I suppose you can never know C++ fully. I would have never guessed
this actually compiles and works:

struct Point { int x, y; };

struct Line
{
Point endpoint[2];
int weight;
};

Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}
This is using the C subset of C++, for both data objects and
initialization, and is perfectly fine as it is. But just add a ctor to
Point or Line to make them non-POD and the initialization would be
illegal.

AFAIK the next C++ standard will relax some constraints for PODness and
add some syntax for convenient initialization of genuine C++ classes as
well.

Paavo

Jul 3 '08 #3
On Jul 3, 9:05*am, Juha Nieminen <nos...@thanks.invalidwrote:
struct Point { int x, y; };

struct Line
{
* * Point endpoint[2];
* * int weight;
};

Line createLine(int sx, int sy, int ex, int ey)
{
* * Line l = { sx, sy, ex, ey, 1 };
* * return l;
}

* Both gcc and Visual Studio 2005 compile that happily.

* My question would be: Is that *really* correct, or are both compilers
simply being lenient? What are the exact rules for the initialization
blocks of structs?
The compilers are not being lenient - multiple braces can be elided in
an aggregate initializer. Therefore, a program can replace this:

Line l = {{{sx, sy}, {ex, ey}}, 1 };

with:

Line l = {sx, sy, ex, ey, 1 };

as long as there are enough arguments to match the aggregate members.
Otherwise, the braces would be needed. For example:

Line l = {{{sx, xy}}, 1}; // l.endpoint[1] is initialized to {0,
0}

I would leave the braces in an aggregate initializer (even when not
needed) just to make the code more readable.

Greg
Jul 3 '08 #4
On Jul 3, 6:05 pm, Juha Nieminen <nos...@thanks.invalidwrote:
I suppose you can never know C++ fully. I would have never
guessed this actually compiles and works:
struct Point { int x, y; };
struct Line
{
Point endpoint[2];
int weight;
};
Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}
Why shouldn't it?
Both gcc and Visual Studio 2005 compile that happily.
My question would be: Is that *really* correct, or are both
compilers simply being lenient? What are the exact rules for
the initialization blocks of structs?
The same as in C, at least in the case of POD agglomerates. In
the places I've worked, it's generally considered good practice
to put in all of the braces, e.g.:

Line l = { { { sx, sy }, { ex, ey } }, 1 } ;

but the language allows many or all of them to be elided. (The
exact rules are fairly complex, and in a code review, I would
reject any code that elided some without eliding all. But
initializers like the one you present were common in C, and so
are legal in C++ as well.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 4 '08 #5
On Jul 3, 9:57 pm, Paavo Helde <nob...@ebi.eewrote:
Juha Nieminen <nos...@thanks.invalidkirjutas:
I suppose you can never know C++ fully. I would have never
guessed this actually compiles and works:
struct Point { int x, y; };
struct Line
{
Point endpoint[2];
int weight;
};
Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}
This is using the C subset of C++, for both data objects and
initialization, and is perfectly fine as it is. But just add a
ctor to Point or Line to make them non-POD and the
initialization would be illegal.
The exact form he has written would become illegal, but
aggregate initialization is legal for any aggregate, and there's
no problem with something like:

class Point
{
int x ;
int y ;
public:
Point( int a, int b ) ;
// other functions as well...
} ;

struct Line
{
Point endpoint[ 2 ] ;
int weight ;
} ;

Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { Point( sx, sy ), Point( ex, ey ), 1 };
return l;
}

(IIRC, some older versions of VC++ didn't accept this. But that
was a bug in the compiler---it's always been perfectly legal.)
AFAIK the next C++ standard will relax some constraints for
PODness and add some syntax for convenient initialization of
genuine C++ classes as well.
There are several important evolutions concerning
initialization, although I'm not too sure about the details. I
do know, however, that one of the goals was to reduce the
differences in the initialization syntax according to whether
the class was an agglomerate or not.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 4 '08 #6
On Jul 4, 8:16 pm, James Kanze <james.ka...@gmail.comwrote:
On Jul 3, 6:05 pm, Juha Nieminen <nos...@thanks.invalidwrote:
Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}
initializers like the one you present were common in C, and so
are legal in C++ as well.)
A minor point; the above initialization is
illegal in C90 which requires initializers
to be constant expressions.

Jul 4 '08 #7
Old Wolf wrote:
On Jul 4, 8:16 pm, James Kanze <james.ka...@gmail.comwrote:
>On Jul 3, 6:05 pm, Juha Nieminen <nos...@thanks.invalidwrote:
>>Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
return l;
}
initializers like the one you present were common in C, and so
are legal in C++ as well.)

A minor point; the above initialization is
illegal in C90 which requires initializers
to be constant expressions.
I thought that was only the case with array initialization. (Or is it
the other way around nowadays?)
Jul 4 '08 #8
On Jul 5, 4:00 am, Juha Nieminen <nos...@thanks.invalidwrote:
Old Wolf wrote:
On Jul 3, 6:05 pm, Juha Nieminen <nos...@thanks.invalidwrote:
Line createLine(int sx, int sy, int ex, int ey)
{
Line l = { sx, sy, ex, ey, 1 };
A minor point; the above initialization is
illegal in C90 which requires initializers
to be constant expressions.

I thought that was only the case with array initialization. (Or is it
the other way around nowadays?)
Nowadays (C99) the above is allowed. But in C90
brace-enclosed initializers (for structs and
arrays) had to be constant expressions.
Jul 5 '08 #9
On Jul 4, 6:54 pm, Old Wolf <oldw...@inspire.net.nzwrote:
On Jul 5, 4:00 am, Juha Nieminen <nos...@thanks.invalidwrote:
Old Wolf wrote:
>>{
>> Line l = { sx, sy, ex, ey, 1 };
A minor point; the above initialization is
illegal in C90 which requires initializers
to be constant expressions.
I thought that was only the case with array initialization. (Or is it
the other way around nowadays?)

Nowadays (C99) the above is allowed. But in C90
brace-enclosed initializers (for structs and
arrays) had to be constant expressions.
No, C99 has the same, const-expression initializer requirements for
arrays - as C90 did: namely, that the initializers for arrays with
static storage duration must be constant expressions, whereas the
initializers for arrays with other-than-static storage duration have
no such requirement

So the initializer of "l" array above would be legal (in both C90 and
C99) - just as long as the "l" array is a local variable.

Greg

Jul 5 '08 #10
On Jul 5, 5:27 am, Greg Herlihy <gre...@mac.comwrote:
On Jul 4, 6:54 pm, Old Wolf <oldw...@inspire.net.nzwrote:
On Jul 5, 4:00 am, Juha Nieminen <nos...@thanks.invalidwrote:
Old Wolf wrote:
>{
> Line l = { sx, sy, ex, ey, 1 };
A minor point; the above initialization is
illegal in C90 which requires initializers
to be constant expressions.
I thought that was only the case with array
initialization. (Or is it the other way around nowadays?)
Nowadays (C99) the above is allowed. But in C90
brace-enclosed initializers (for structs and
arrays) had to be constant expressions.
No, C99 has the same, const-expression initializer
requirements for arrays - as C90 did: namely, that the
initializers for arrays with static storage duration must be
constant expressions, whereas the initializers for arrays with
other-than-static storage duration have no such requirement
That's what I always thougt too, but on pulling out my old
copy of C90, I find (§6.5.7, in the Constraints section):

All of the expressions in an initializer for an object
that has static storage duration or in an initializer
list for an object that has aggregate or union type
shall be constant expressions.

And in §6.1.2.5, "Array and structure types are collectively
called aggregate types" (with "aggregate types" in italics,
so this is a definition).

Historically, of course, K&R C required constant expressions
for all aggregate initialization, and C99 only requires them
for variables with static lifetime. Apparently, the change
didn't take place until after C90 (although I remember it as
being before).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 5 '08 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
507
by: John Smith | last post by:
Is this a no-no? My compiler doesn't like it. typedef struct cplex { double real; double imag; } cplex; int main(void) { cplex a;
4
3665
by: Everton | last post by:
The task at hand is to initialize a variable of type "struct in6_addr" in a portable way. For instance: /* NetBSD - /usr/include/netinet6/in6.h */ struct in6_addr { union { __uint8_t ...
3
4140
by: jilerner | last post by:
Question about C99/gcc struct initialization: void ffoo(void) { struct FOO { int a,b,c; }; struct foo = { .b = 22 }; What happens now to foo.a and foo.c ? Are they initialized to 0, or left...
21
10530
by: Zytan | last post by:
Is it possible, as in C? I don't think it is. Just checking. Zytan
6
15049
by: Daniel Rudy | last post by:
Hello Group. Please consider the following code: /* this table is used in the wipedevice routine */ static const struct wipe_t { uchar wte; /* wipe table entry */ } wipetable = {...
2
3874
by: dj3vande | last post by:
Is this code, as the complete contents of a translation unit, valid C90 that initializes the struct foo to contain copies of the values passed to bar()? -------- struct foo { int i; void *v;...
2
1858
by: quadraticformula | last post by:
Hey, quick question for anyone willing to listen. I've always wondered why I can initialize an array of structs with something like this (where "..." represents the 14 separate values for the...
0
7180
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6846
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7341
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5439
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4870
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4564
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3071
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1381
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
600
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.