Compound literals and VLA's

W

William Ahern

So, GCC 4.01 is giving errors that GCC 3.3 did not, and I'm thinking they've
gone overboard with their new type checking infrastructure.

Here's the supposedly offending code (no laughing or grimacing, please ;)

char *s, *s1;

s1 = strcpy((char [strlen(s) + 1]){ },s);

and GCC 4.01's error messages

error: compound literal has variable size
error: empty scalar initializer
error: (near initialization for `(anonymous)')

First, is it really illegal to define a variable size for the compound array
literal? Do compound literals and VLA's not mix? If I store the array length
in a variable I get the same error.

Second, what is up with "empty scalar initializer"? If I add an explicit
zero--{ 0 }--the error obviously goes away. Does the "as if zero" rule not
apply if no initializers are given?

I realize GCC behavior is off-topic, but I'm curious what the conensus is on
the proper behavior.

- Bill
 
B

Ben Pfaff

Finally, a really interesting question. I see so few questions I
want to answer these days. Either the quality of the questions
is declining or my pickiness is increasing. Probably the latter.

William Ahern said:
Here's the supposedly offending code (no laughing or grimacing, please ;)

char *s, *s1;

s1 = strcpy((char [strlen(s) + 1]){ },s);

and GCC 4.01's error messages

error: compound literal has variable size
error: empty scalar initializer
error: (near initialization for `(anonymous)')
First, is it really illegal to define a variable size for the compound array
literal? Do compound literals and VLA's not mix? If I store the array length
in a variable I get the same error.

Here's your relevant C99 quote:

6.5.2.5 Compound literals

Constraints

1 The type name shall specify an object type or an array of
unknown size, but not a variable length array type.

Go on and ask a hard one :)
Second, what is up with "empty scalar initializer"? If I add an explicit
zero--{ 0 }--the error obviously goes away. Does the "as if zero" rule not
apply if no initializers are given?

A compound literal has this syntax:

( type-name ) { initializer-list }

with the important sub-definitions being these:

initializer-list:
designation_opt initializer
initializer-list , designation_opt initializer

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }

In other words, the braces are not allowed to be empty. { ... }
contains an initializer-list, an initializer-list contains at
least one initializer, which contains an expression (or a
sub-initializer-list), and an expression cannot be empty[*].

[*] An expression *statement* can be empty but that's because of
the syntax of expression-statement, not of the syntax of an
expression.
 
R

Robert Gamble

William said:
So, GCC 4.01 is giving errors that GCC 3.3 did not, and I'm thinking they've
gone overboard with their new type checking infrastructure.

Here's the supposedly offending code (no laughing or grimacing, please ;)

char *s, *s1;

s1 = strcpy((char [strlen(s) + 1]){ },s);

and GCC 4.01's error messages

error: compound literal has variable size
error: empty scalar initializer
error: (near initialization for `(anonymous)')

First, is it really illegal to define a variable size for the compound array
literal? Do compound literals and VLA's not mix? If I store the array length
in a variable I get the same error.

You cannot create a compound literal with variable length array type,
attempting to do so is a constraint violation (6.5.2.5p1) and it's a
good thing that gcc finally produces a diagnostic for this.
Second, what is up with "empty scalar initializer"? If I add an explicit
zero--{ 0 }--the error obviously goes away. Does the "as if zero" rule not
apply if no initializers are given?

I have never heard of the "as if zero rule" but no, this is not
allowed. You can't have an empty initializer list for any array type
(i.e. int i[5] = {}; is not legal), what would make you think you can
do so here?

Robert Gamble
 
W

William Ahern

I have never heard of the "as if zero rule" but no, this is not
allowed. You can't have an empty initializer list for any array type
(i.e. int i[5] = {}; is not legal), what would make you think you can
do so here?

Given
struct {
int a;
int b;
} x = {
.b = 0,
};

then x.a is initialized "as-if" the initializer literally had ".a = 0". IOW,
all unnamed members are initialized "as-if" set to zero.

In C99, along with named initializers for structures, you can also
initialize specified indices of arrays

const char map[10] = { .[3] = '\n', };

All the other indices are initialized to zero.

I suppose my understanding of this behavior and nomenclature was
insufficiently exact, thus my confusion.
 
W

William Ahern

Ben Pfaff said:
Finally, a really interesting question. I see so few questions I
want to answer these days. Either the quality of the questions
is declining or my pickiness is increasing. Probably the latter.

Thanks for coming out of the woodword, and for the very helpful answer. I'm
ashamed to say I have a hard copy of the C99 standard on my desk. I thought
I had tried to find the relevant section(s) last week. Either my memory is
failing me or I'm becoming too lazy... or both. (That, and I still
haven't develop a knack for finding stuff in the darn thing.)
 
B

Ben Pfaff

William Ahern said:
I'm ashamed to say I have a hard copy of the C99 standard on my
desk. I thought I had tried to find the relevant section(s)
last week. Either my memory is failing me or I'm becoming too
lazy... or both. (That, and I still haven't develop a knack for
finding stuff in the darn thing.)

In my opinion: don't bother trying to find anything in the hard
copy. Unless you already know where to look, you probably won't
find what you're looking for. Instead, do full text search on
the PDF version or, as I do, convert the PDF version to plain
text and search that.
 
R

Robert Gamble

William said:
I have never heard of the "as if zero rule" but no, this is not
allowed. You can't have an empty initializer list for any array type
(i.e. int i[5] = {}; is not legal), what would make you think you can
do so here?

Given
struct {
int a;
int b;
} x = {
.b = 0,
};

then x.a is initialized "as-if" the initializer literally had ".a = 0". IOW,
all unnamed members are initialized "as-if" set to zero.

In C99, along with named initializers for structures, you can also
initialize specified indices of arrays

const char map[10] = { .[3] = '\n', };

That should actually be:

const char map[10] = { [3] = '\n' };

the dot syntax is for structures, the bracket syntax is for arrays, and
the trailing comma, although allowed (see the syntax Ben provided in
his excellent response), is not required.
All the other indices are initialized to zero.

I suppose my understanding of this behavior and nomenclature was
insufficiently exact, thus my confusion.

Yes, members of arrays and structures not explicitly initialized in an
initializer list are implicitly initialized following the same rules as
objects with static duration (arithmetic types to 0, pointers to null).
I had never heard of this referred to as the "as if zero" which was
the cause for my confusion.

Robert Gamble
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top