Thread: brace-enclosed error

  1. #46
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >I was irritated by a separate thread to imply that I was blind.
    Well that was really meant for the thread as a whole. If you take the initial premise that the code would not compile for the OP, then what is the solution? I felt the solution was to remove the offending braces (the braces for members which were not array items), whether the C++ standard said to or not. I guess I was wrong.

  2. #47
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I can confirm that compiling Dave_Sinkula's sample code with the MinGW port of gcc 3.4.2 gives warnings about "braces around scalar initializer". Compiling with g++ instead gives errors about "brace-enclosed initializer used to initialize 'UInt8'".

    Section 8.5 of the C++ Standard states:
    If T is a scalar type, then a declaration of the form
    Code:
    T x = { a };
    is equivalent to
    Code:
    T x = a;
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #48
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Hmm, that's curious. So according to the C++ standard it should compile, but g++ does not like it. And gcc 3.4.2 accepts it, but issues warnings. Strange indeed.

  4. #49
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Oh, but the plot thickens. I am probably missing some obvious text in the standard, as the online Comeau compiler tells me:
    Code:
    Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
    Copyright 1988-2007 Comeau Computing.  All rights reserved.
    MODE:strict errors C++ C++0x_extensions
    
    "ComeauTest.c", line 9: error: extra braces are nonstandard
          Test test = {1, {2}};
                          ^
    
    "ComeauTest.c", line 9: warning: variable "test" was declared but never referenced
          Test test = {1, {2}};
               ^
    
    1 error detected in the compilation of "ComeauTest.c".
    For the test code:
    Code:
    struct Test
    {
        int x;
        int y;
    };
    
    int main()
    {
        Test test = {1, {2}};
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #50
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I tried your test code with Borland, and it compiles without warnings in both C++ mode and C mode (with minor changes). Actually there were warnings, but not pertaining to the struct. I'll try it with Dev-C++ later today, but expect to get the same result you got Lasarlight with MinGW.

  6. #51
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    My theory is that in this context Comeau and other compilers are expecting nested structures or an array here, where braces would be okay. It could also be reasonably disputed that despite ints being scalar, a structure is not, and therefore extra braces are non-standard. But there is some safe leeway here, so I doubt it matters tremendously. If the compiler complains, you can delete the braces right?

    Whether this rule is something that was introduced with C++ or simply not enforced in standard C is something beyond my knowledge right now.

  7. #52
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I was doing some searching earlier in the day and discovered some things regarding my threadjacking here.

    I tried the Comeau compiler, but was having issues with C++ options for C compiling, so I asked them about this as well. Some selected quotes:
    >Essentially it involves "The initializer for a scalar shall be a
    >single expression, optionally enclosed in braces."
    >http://web.archive.org/web/200502070...aft.html#3.5.7

    That's misleading words probably, since we recall a paragraph or two
    later there is more words basically saying "... and if it is an
    aggregate... do this instead" hence in contrast the the scalar.


    >If you don't mind wandering through an existing thread for further
    >clarification, my curiousity with this issue started about here:
    >http://cboard.cprogramming.com/showt...083#post640083 or
    >http://cboard.cprogramming.com/showt...125#post640125

    Generally, C and C++ should be saying the same things, except (and
    this is off the top of our heads) they don't use exactly the same
    words, each has had their wording tweaking as per their respective
    defect reports processing, and also, seem to recall C++ explicitly
    makes some of the case ill-formed, whereas in C it's left
    undefined. Probably in both cases, the problem boils down to that
    the wording probably lead into that there is an extra initializer
    being brought forth (the scalar member is left unitialized, and then
    the {}s try to init a non-existant sub-aggregate). Either that, or
    you've found a problem with both standards.
    > > Well, at least in one you're comparing two different things:
    > >
    > > int x = { 42 };
    > >
    > > is allowed in C++. But as mentioned, we recall it's ill-formed when
    > > used as an aggregate initializer. The words to handle this is both
    > > standards are not fun, so as mentioned, it good be there is a problem
    > > with the words.
    >
    >Okay, so is it that scalar *members* of aggregates do not allow this?

    We think it could be worded clearer, but yes, we believe that is the
    intention.
    FWIW, we recalled this
    http://www.comeaucomputing.com/iso/cwg_defects.html#163 We'll need
    to review which side of the fence this leaves/brings the situation
    And some other searching got me to the C90 rationale:
    Various implementations have parsed aggregate initializers with partially elided braces differently. The Standard has reaffirmed the (top-down) parse described in the Base Document. Although the construct is allowed, and its parse well defined, the Committee urges programmers to avoid partially elided initializers: such initializations can be quite confusing to read.

    QUIET CHANGE



    Code which relies on a bottom-up parse of aggregate initializers with partially elided braces will not yield the expected initialized object.
    And this interesting number from Sun's documention:
    [ISO C]Uses a top-down parsing algorithm. For example:
    Code:
    struct{int a[3];int b;}\ 
    w[]={{1},2};
    yields
    Code:
    sizeof(w)=32 
    w[0].a=1,0,0 
    w[0].b=0 
    w[1].a=2,0,0 
    w[1].b=0
    [K&R]Uses a bottom-up algorithm when parsing and processing partially elided initializers within braces:
    Code:
    struct{ int a[3]; int b; }\
    w[]={{1},2};
    yields
    Code:
    sizeof(w)=16 
    w[0].a=1,0,0 
    w[0].b=2
    Experimenting with my newly-learned term, "partially elided braces", and from Sun's docs, I just had to give this a go:
    Code:
    #include <stdio.h>
    
    int main(void)
    {
       struct { int a[3]; int b; } w[] = { { { 1 }, 2 } }, 
                                   x[] = {   { 1 }, 2   }; 
       printf("sizeof w = &#37;lu\n", (long unsigned)sizeof w);
       printf("sizeof x = %lu\n", (long unsigned)sizeof x);
       return 0;
    }
    
    /*
    sizeof w = 16
    sizeof x = 32
    */
    I believe I've already mentioned the defect, but it is also here.

    And another related thread I found along the way.

    FWIW


    [edit]Oh, and regarding my issue with the online compiler:
    >http://www.redacted.com/

    That's a dead link. But we put two and two together and figured out
    that C++ extensions were being requested in some C modes. It should
    now be ok.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #53
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I ran your sample code through Borland, and the output was the same (16 and 32).

    Lots of food for thought there Dave, I'm still reading some of it. Near as I can tell, Comeau thinks its compiler is correct, but they can't quite explain why. I'll reread some of this tomorrow. Maybe it'll make more sense.

    It does seem to make sense that the output for the sample code is 16 and 32, given that the standards committee says the parse is top-down. So each time you encounter a left-brace, that's a new subobject.

  9. #54
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    More digging...

    Standard C/Bugs
    [...]

    So for all these reasons, I stuffed the library through a C++ compiler and shook out the nits. Two language differences led to numerous changes. One was the meaning of void pointers. The other was the use of braces in initializers.

    [...]

    The third largest batch was data initializers. I found that I had much less latitude in writing braces in C++ than in C. Partially bracketed initializers are a no-no. But so too are braces around a scalar initializer, as in:
    Code:
    static const double sqrt2 =
        {1.41421356237309505};    /* BAD C++ */

    I still don't know whether this is a C++ requirement or a peculiarity of Turbo C++. I haven't read the draft C++ standard in sufficient detail to find out. In either event, I figure that the tighter rules are probably a good idea. C compilers have been notoriously inconsistent in how they interpret initializers with elided braces. Even the C Standard seems to confuse more people than it helps in this area.
    C++ Standard Core Language Active Issues, Revision 46
    155. Brace initializer for scalar

    Section: 8.5 dcl.init <http://www.open-std.org/jtc1/sc22/wg21/docs/decl.html#dcl.init> Status: open Submitter: Steve Clamage Date: 12 Aug 1999


    It is not clear whether the following declaration is well-formed:
    Code:
    struct S { int i; } s = { { 1 } };
    According to 8.5.1 dcl.init.aggr <http://www.open-std.org/jtc1/sc22/wg21/docs/decl.html#dcl.init.aggr> paragraph 2, a brace-enclosed initializer is permitted for a subaggregate of an aggregate; however, i is a scalar, not an aggregate. 8.5 dcl.init <http://www.open-std.org/jtc1/sc22/wg21/docs/decl.html#dcl.init> paragraph 13 says that a standalone declaration like
    Code:
    int i = { 1 };
    is permitted, but it is not clear whether this says anything about the form of initializers for scalar members of aggregates.

    This is (more) clearly permitted by the C89 Standard.
    But essentially I believe my questions are answered:
    1. C and C++ do differ when it comes to partially elided braces.
    2. Scalar members of aggregates don't have the same optional braces rule for initializers as "plain" scalars.
    My main interest was in a construct like this:
    Code:
    type value = {0};
    I had come to understand it as a "magic" construct that worked for all types.

    Well, it's still true in that respect and for both languages, but now I know that this doesn't extended to members of an aggregate or union. (Well, I suppose a union might have possible issues. And the compiler may still dispatch good-intentioned warnings.)

    ---

    This issue appears to have already come up with the C++ folks. And the confusing stuff I failed to parse in the C standard is apparently that way by design.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  3. How to monitor process creation?
    By markiz in forum Windows Programming
    Replies: 31
    Last Post: 03-17-2008, 02:39 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM