Is this type of char array initization legal?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • DomoChan@gmail.com

    Is this type of char array initization legal?

    the code below will compile in visual c++ 2003, but im not sure its
    valid.

    unsigned char myString[200] = "";

    after this line executes, all the bytes within myString are indeed set
    to '0's' but is this really valid c++ or c? where can I find out how
    this is implemented?

    Im concerned because I had a 3rd party library wrapper which was
    crashing, and I was able to alleviate the crash by changing the
    initialization method from the above to ...

    unsigned char myString[200];

    memset( myString, 0, sizeof( myString ) );

    any guidance is greatly appreciated!
    -Velik
  • Victor Bazarov

    #2
    Re: Is this type of char array initization legal?

    DomoChan@gmail. com wrote:
    the code below will compile in visual c++ 2003, but im not sure its
    valid.
    >
    unsigned char myString[200] = "";
    >
    after this line executes, all the bytes within myString are indeed set
    to '0's' but is this really valid c++ or c? where can I find out how
    this is implemented?
    >
    Im concerned because I had a 3rd party library wrapper which was
    crashing, and I was able to alleviate the crash by changing the
    initialization method from the above to ...
    >
    unsigned char myString[200];
    >
    memset( myString, 0, sizeof( myString ) );
    >
    any guidance is greatly appreciated!
    -Velik
    It is valid. Allowed explicitly by the Standard, subclause 8.5.2.

    The only reason it could be crashing is if the compiler wastn't
    providing proper initialisation for the array. What you could do is
    revert this to what it was and put an assertion to see if it's indeed
    the problem:

    unsigned char myString[200] = "";
    #ifndef NDEBUG
    for (int iii = 0; iii < 200; ++iii)
    ASSERT(myString[iii] == 0);
    #endif

    Now, if you are saying that you verified that all elements of the array
    are indeed set to 0 after the initialisation, then it's OK, and the
    crash is due to some other problem which you just *hid* by introducing
    your 'memset' "fix", most likely.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask

    Comment

    • Pete Becker

      #3
      Re: Is this type of char array initization legal?

      On 2008-10-24 12:22:09 -0400, DomoChan@gmail. com said:
      the code below will compile in visual c++ 2003, but im not sure its
      valid.
      >
      unsigned char myString[200] = "";
      >
      after this line executes, all the bytes within myString are indeed set
      to '0's' but is this really valid c++ or c? where can I find out how
      this is implemented?
      They're set to zero if myString has static storage duration, and that's
      also true with no initializer. If it has automatic storage duration,
      myString[0] is set to 0.
      >
      Im concerned because I had a 3rd party library wrapper which was
      crashing, and I was able to alleviate the crash by changing the
      initialization method from the above to ...
      >
      unsigned char myString[200];
      >
      memset( myString, 0, sizeof( myString ) );
      >
      any guidance is greatly appreciated!
      Apparently the third-party library requires an array with all elements
      set to zero. That requirement should be in the documentation for the
      library.

      --
      Pete
      Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
      Standard C++ Library Extensions: a Tutorial and Reference
      (www.petebecker.com/tr1book)

      Comment

      • Gennaro Prota

        #4
        Re: Is this type of char array initization legal?

        DomoChan@gmail. com wrote:
        the code below will compile in visual c++ 2003, but im not sure its
        valid.
        >
        unsigned char myString[200] = "";
        >
        after this line executes, all the bytes within myString are indeed set
        to '0's' but is this really valid c++ or c? where can I find out how
        this is implemented?
        >
        Im concerned because I had a 3rd party library wrapper which was
        crashing, and I was able to alleviate the crash by changing the
        initialization method from the above to ...
        >
        unsigned char myString[200];
        >
        memset( myString, 0, sizeof( myString ) );
        >
        any guidance is greatly appreciated!
        Practical advice: change it to

        unsigned char myString[ 200 ] = {} ;

        What to you mean by "alleviate" the crash?

        PS: the language lawyering behind the first initialization is a
        bit more complicated than I have time to explain; consider that
        the array elements are of type unsigned char (not char) and that
        there was a C standard clarification in this area which C++
        hasn't picked up (though your C++ compiler might de-facto
        implement it).

        <http://groups.google.c om/group/comp.lang.c++/msg/d5ac14fbe55de25 b>

        --
        Gennaro Prota | name.surname yahoo.com
        Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
        Do you need expertise in C++? I'm available.

        Comment

        • Pete Becker

          #5
          Re: Is this type of char array initization legal?

          On 2008-10-24 12:49:25 -0400, Victor Bazarov <v.Abazarov@com Acast.netsaid:
          DomoChan@gmail. com wrote:
          >the code below will compile in visual c++ 2003, but im not sure its
          >valid.
          >>
          >unsigned char myString[200] = "";
          >>
          >after this line executes, all the bytes within myString are indeed set
          >to '0's' but is this really valid c++ or c? where can I find out how
          >this is implemented?
          >>
          >Im concerned because I had a 3rd party library wrapper which was
          >crashing, and I was able to alleviate the crash by changing the
          >initializati on method from the above to ...
          >>
          >unsigned char myString[200];
          >>
          >memset( myString, 0, sizeof( myString ) );
          >>
          >any guidance is greatly appreciated!
          >
          It is valid. Allowed explicitly by the Standard, subclause 8.5.2.
          >
          The only reason it could be crashing is if the compiler wastn't
          providing proper initialisation for the array. What you could do is
          revert this to what it was and put an assertion to see if it's indeed
          the problem:
          >
          unsigned char myString[200] = "";
          #ifndef NDEBUG
          for (int iii = 0; iii < 200; ++iii)
          ASSERT(myString[iii] == 0);
          #endif
          Hmm, is this required if the char array has automatic storage duration?
          I have always assumed that it wasn't, that only the characters
          corresponding to characters in the initializer would be initialized,
          but it doesn't seem completely clear from a quick glance at the
          standard.

          --
          Pete
          Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
          Standard C++ Library Extensions: a Tutorial and Reference
          (www.petebecker.com/tr1book)

          Comment

          • Salt_Peter

            #6
            Re: Is this type of char array initization legal?

            On Oct 24, 12:22 pm, DomoC...@gmail. com wrote:
            the code below will compile in visual c++ 2003, but im not sure its
            valid.
            >
            unsigned char myString[200] = "";
            >
            after this line executes, all the bytes within myString are indeed set
            to '0's'  but is this really valid c++ or c?  where can I find out how
            this is implemented?
            Sounds like you see the results of a program in debug mode. The string
            literal "" is actually {'\0'} so everything after myString[0] has an
            undeterminate value. Nobody cares whether some compiler initializes or
            not the rest of the array with some magic value, there is no
            requirement that says it must.
            >
            Im concerned because I had a 3rd party library wrapper which was
            crashing, and I was able to alleviate the crash by changing the
            initialization method from the above to ...
            >
            unsigned char myString[200];
            >
            memset( myString, 0, sizeof( myString ) );
            >
            any guidance is greatly appreciated!
            -Velik
            An array has a special initializer that looks like so:
            unsigned char myString[200] = {'a'};
            which initializes all elements with 'a' in this case.
            Note the element type of the array (unsigned char) and the type in the
            array init list.
            Now having said that, the above is an array, not a terminated sequence
            of unsigned characters.

            Another reason to prefer modern containers:

            #include <vector>

            // all elements initialized: guarenteed
            std::vector< unsigned char vuc(200);

            // all 'a'
            std::vector< unsigned char vuca(200, 'a');

            Comment

            • Pete Becker

              #7
              Re: Is this type of char array initization legal?

              On 2008-10-24 13:35:25 -0400, Salt_Peter <pj_hern@yahoo. comsaid:
              On Oct 24, 12:22 pm, DomoC...@gmail. com wrote:
              >the code below will compile in visual c++ 2003, but im not sure its
              >valid.
              >>
              >unsigned char myString[200] = "";
              >>
              >after this line executes, all the bytes within myString are indeed set
              >to '0's'  but is this really valid c++ or c?  where can I find out ho
              w
              >this is implemented?
              >
              Sounds like you see the results of a program in debug mode.
              In which case, the debug mode needs further thought. Initializing to
              all zeros is a bad idea when debugging, because the result looks like
              good data.
              The string
              literal "" is actually {'\0'} so everything after myString[0] has an
              undeterminate value. Nobody cares whether some compiler initializes or
              not the rest of the array with some magic value, there is no
              requirement that says it must.
              >
              >>
              >Im concerned because I had a 3rd party library wrapper which was
              >crashing, and I was able to alleviate the crash by changing the
              >initializati on method from the above to ...
              >>
              >unsigned char myString[200];
              >>
              >memset( myString, 0, sizeof( myString ) );
              >>
              >any guidance is greatly appreciated!
              >-Velik
              >
              An array has a special initializer that looks like so:
              unsigned char myString[200] = {'a'};
              which initializes all elements with 'a' in this case.
              This is just straight aggregate initialization, and it initializes all
              values after the end of the initializer to 0, not to the value of the
              initializer.

              --
              Pete
              Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
              Standard C++ Library Extensions: a Tutorial and Reference
              (www.petebecker.com/tr1book)

              Comment

              • Victor Bazarov

                #8
                Re: Is this type of char array initization legal?

                Pete Becker wrote:
                On 2008-10-24 12:49:25 -0400, Victor Bazarov <v.Abazarov@com Acast.net>
                said:
                >
                >DomoChan@gmail. com wrote:
                >>the code below will compile in visual c++ 2003, but im not sure its
                >>valid.
                >>>
                >>unsigned char myString[200] = "";
                >>>
                >>after this line executes, all the bytes within myString are indeed set
                >>to '0's' but is this really valid c++ or c? where can I find out how
                >>this is implemented?
                >>>
                >>Im concerned because I had a 3rd party library wrapper which was
                >>crashing, and I was able to alleviate the crash by changing the
                >>initializatio n method from the above to ...
                >>>
                >>unsigned char myString[200];
                >>>
                >>memset( myString, 0, sizeof( myString ) );
                >>>
                >>any guidance is greatly appreciated!
                >>
                >It is valid. Allowed explicitly by the Standard, subclause 8.5.2.
                >>
                >The only reason it could be crashing is if the compiler wastn't
                >providing proper initialisation for the array. What you could do is
                >revert this to what it was and put an assertion to see if it's indeed
                >the problem:
                >>
                > unsigned char myString[200] = "";
                >#ifndef NDEBUG
                > for (int iii = 0; iii < 200; ++iii)
                > ASSERT(myString[iii] == 0);
                >#endif
                >
                Hmm, is this required if the char array has automatic storage duration?
                I have always assumed that it wasn't, that only the characters
                corresponding to characters in the initializer would be initialized, but
                it doesn't seem completely clear from a quick glance at the standard.
                >
                8.5.1/7:
                <<If there are fewer initializers in the list than there are members in
                the aggregate, then each member not
                explicitly initialized shall be value-initialized (8.5).>>

                To me it's pretty clear. Each character from the literal initialises
                its respective element of the array. The terminating null character
                does initialise the corresponding element of the array *too*. If there
                are fewer characters in the literal than elements in the array (which is
                an aggregate), the rest of the array elements are zero-initialised.

                V
                --
                Please remove capital 'A's when replying by e-mail
                I do not respond to top-posted replies, please don't ask

                Comment

                • Default User

                  #9
                  Re: Is this type of char array initization legal?

                  Pete Becker wrote:
                  On 2008-10-24 12:49:25 -0400, Victor Bazarov
                  <v.Abazarov@com Acast.netsaid:
                  The only reason it could be crashing is if the compiler wastn't
                  providing proper initialisation for the array. What you could do
                  is revert this to what it was and put an assertion to see if it's
                  indeed the problem:

                  unsigned char myString[200] = "";
                  #ifndef NDEBUG
                  for (int iii = 0; iii < 200; ++iii)
                  ASSERT(myString[iii] == 0);
                  #endif
                  >
                  Hmm, is this required if the char array has automatic storage
                  duration? I have always assumed that it wasn't, that only the
                  characters corresponding to characters in the initializer would be
                  initialized, but it doesn't seem completely clear from a quick glance
                  at the standard.
                  Interesting. I also didn't find anything explicit regarding string
                  literals, just the usual "fewer initializer" rule:

                  If there are fewer initializers in the list than there are
                  members in the aggregate, then each member not explicitly
                  initialized shall be value-initialized (8.5).

                  The C standard does contain such wording (assuming that it didn't
                  change from the draft standard):

                  [#21] If there are fewer initializers in a brace-enclosed
                  list than there are elements or members of an aggregate, or
                  fewer characters in a string literal used to initialize an
                  array of known size than there are elements in the array,
                  the remainder of the aggregate shall be initialized
                  implicitly the same as objects that have static storage
                  duration.

                  C89's wording was similar to the C++ standard, but had further examples
                  to show that initialization with a string literal is identical to a
                  brace-enclosed list of the characters, which would amount to the same
                  thing.




                  Brian

                  Comment

                  • Pete Becker

                    #10
                    Re: Is this type of char array initization legal?

                    On 2008-10-24 16:18:56 -0400, Victor Bazarov <v.Abazarov@com Acast.netsaid:
                    Pete Becker wrote:
                    >On 2008-10-24 12:49:25 -0400, Victor Bazarov <v.Abazarov@com Acast.netsaid:
                    >>
                    >>DomoChan@gmail. com wrote:
                    >>>the code below will compile in visual c++ 2003, but im not sure its
                    >>>valid.
                    >>>>
                    >>>unsigned char myString[200] = "";
                    >>>>
                    >>>after this line executes, all the bytes within myString are indeed set
                    >>>to '0's' but is this really valid c++ or c? where can I find out how
                    >>>this is implemented?
                    >>>>
                    >>>Im concerned because I had a 3rd party library wrapper which was
                    >>>crashing, and I was able to alleviate the crash by changing the
                    >>>initializati on method from the above to ...
                    >>>>
                    >>>unsigned char myString[200];
                    >>>>
                    >>>memset( myString, 0, sizeof( myString ) );
                    >>>>
                    >>>any guidance is greatly appreciated!
                    >>>
                    >>It is valid. Allowed explicitly by the Standard, subclause 8.5.2.
                    >>>
                    >>The only reason it could be crashing is if the compiler wastn't
                    >>providing proper initialisation for the array. What you could do is
                    >>revert this to what it was and put an assertion to see if it's indeed
                    >>the problem:
                    >>>
                    >> unsigned char myString[200] = "";
                    >>#ifndef NDEBUG
                    >> for (int iii = 0; iii < 200; ++iii)
                    >> ASSERT(myString[iii] == 0);
                    >>#endif
                    >>
                    >Hmm, is this required if the char array has automatic storage duration?
                    >I have always assumed that it wasn't, that only the characters
                    >correspondin g to characters in the initializer would be initialized,
                    >but it doesn't seem completely clear from a quick glance at the
                    >standard.
                    >>
                    >
                    8.5.1/7:
                    <<If there are fewer initializers in the list than there are members in
                    the aggregate, then each member not
                    explicitly initialized shall be value-initialized (8.5).>>
                    Well, yes, that's the requirement for aggregate initialization. But
                    does aggregate initialization apply here? Aggregate initialization is
                    indicated by "a brace-enclosed, comma-separated list ...", which isn't
                    present here. I don't see anything in 8.5.2 [dcl.init.string] that says
                    that aggregate initialization is used, although the "optionally
                    enclosed in braces" hints that it may be.

                    --
                    Pete
                    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                    Standard C++ Library Extensions: a Tutorial and Reference
                    (www.petebecker.com/tr1book)

                    Comment

                    • Pete Becker

                      #11
                      Re: Is this type of char array initization legal?

                      On 2008-10-24 16:29:45 -0400, "Default User" <defaultuserbr@ yahoo.comsaid:
                      Pete Becker wrote:
                      >
                      >On 2008-10-24 12:49:25 -0400, Victor Bazarov
                      ><v.Abazarov@co mAcast.netsaid:
                      >
                      >>The only reason it could be crashing is if the compiler wastn't
                      >>providing proper initialisation for the array. What you could do
                      >>is revert this to what it was and put an assertion to see if it's
                      >>indeed the problem:
                      >>>
                      >>unsigned char myString[200] = "";
                      >>#ifndef NDEBUG
                      >>for (int iii = 0; iii < 200; ++iii)
                      >>ASSERT(myStri ng[iii] == 0);
                      >>#endif
                      >>
                      >Hmm, is this required if the char array has automatic storage
                      >duration? I have always assumed that it wasn't, that only the
                      >characters corresponding to characters in the initializer would be
                      >initialized, but it doesn't seem completely clear from a quick glance
                      >at the standard.
                      >
                      Interesting. I also didn't find anything explicit regarding string
                      literals, just the usual "fewer initializer" rule:
                      >
                      If there are fewer initializers in the list than there are
                      members in the aggregate, then each member not explicitly
                      initialized shall be value-initialized (8.5).
                      >
                      The C standard does contain such wording (assuming that it didn't
                      change from the draft standard):
                      >
                      [#21] If there are fewer initializers in a brace-enclosed
                      list than there are elements or members of an aggregate, or
                      fewer characters in a string literal used to initialize an
                      array of known size than there are elements in the array,
                      the remainder of the aggregate shall be initialized
                      implicitly the same as objects that have static storage
                      duration.
                      >
                      C89's wording was similar to the C++ standard, but had further examples
                      to show that initialization with a string literal is identical to a
                      brace-enclosed list of the characters, which would amount to the same
                      thing.
                      >
                      So C99 made it crystal clear, presumably because C90 wasn't. <g>

                      --
                      Pete
                      Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                      Standard C++ Library Extensions: a Tutorial and Reference
                      (www.petebecker.com/tr1book)

                      Comment

                      • Default User

                        #12
                        Re: Is this type of char array initization legal?

                        Victor Bazarov wrote:
                        Pete Becker wrote:
                        On 2008-10-24 12:49:25 -0400, Victor Bazarov
                        Hmm, is this required if the char array has automatic storage
                        duration? I have always assumed that it wasn't, that only the
                        characters corresponding to characters in the initializer would be
                        initialized, but it doesn't seem completely clear from a quick
                        glance at the standard.
                        >
                        8.5.1/7:
                        <<If there are fewer initializers in the list than there are members
                        in the aggregate, then each member not explicitly initialized shall
                        be value-initialized (8.5).>>
                        >
                        To me it's pretty clear. Each character from the literal initialises
                        its respective element of the array. The terminating null character
                        does initialise the corresponding element of the array too. If there
                        are fewer characters in the literal than elements in the array (which
                        is an aggregate), the rest of the array elements are zero-initialised.
                        I'm sure it was intended, and it's always been that way in C, but
                        there's some haziness. A string literal isn't a list, exactly. As I
                        pointed out in another reply, the C99 standard added wording to make
                        that explicit, and the older standard had wording that confirmed that a
                        string literal was the same as a character list for intialization
                        purposes.

                        In my experience, a C++ compiler that didn't zero out the rest of the
                        array would be unusual. The OP can certainly check to see if that's the
                        problem.





                        Brian

                        Comment

                        • James Kanze

                          #13
                          Re: Is this type of char array initization legal?

                          On Oct 24, 10:46 pm, Pete Becker <p...@versatile coding.com>
                          wrote:
                          On 2008-10-24 16:18:56 -0400, Victor Bazarov
                          <v.Abaza...@com Acast.netsaid:
                          8.5.1/7:
                          <<If there are fewer initializers in the list than there are members in
                          the aggregate, then each member not
                          explicitly initialized shall be value-initialized (8.5).>>
                          Well, yes, that's the requirement for aggregate
                          initialization. But does aggregate initialization apply here?
                          Aggregate initialization is indicated by "a brace-enclosed,
                          comma-separated list ...", which isn't present here. I don't
                          see anything in 8.5.2 [dcl.init.string] that says that
                          aggregate initialization is used, although the "optionally
                          enclosed in braces" hints that it may be.
                          Well, I rather think it was intended, although you do have a
                          point. Probably a defect in the standard. (Maybe I should
                          raise an issue. I'd love to say that it was just editorial, and
                          just push it off on you, but I think it's a little too much for
                          that.)

                          --
                          James Kanze (GABI Software) email:james.kan ze@gmail.com
                          Conseils en informatique orientée objet/
                          Beratung in objektorientier ter Datenverarbeitu ng
                          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                          Comment

                          • Default User

                            #14
                            Re: Is this type of char array initization legal?

                            Pete Becker wrote:
                            On 2008-10-24 16:29:45 -0400, "Default User"
                            <defaultuserbr@ yahoo.comsaid:
                            C89's wording was similar to the C++ standard, but had further
                            examples to show that initialization with a string literal is
                            identical to a brace-enclosed list of the characters, which would
                            amount to the same thing.
                            >
                            So C99 made it crystal clear, presumably because C90 wasn't. <g>
                            It was, I think, clear enough. It just wasn't all put together nicely.
                            They had examples to show that:

                            char str[] = "XYZ";

                            Was equivalent to:

                            char str[] = {'X', 'Y', 'Z', '\0'};

                            So if a string literal is equivalent to a brace-enclosed list of
                            characters, then the "fewer initializer" rule would come into play to
                            finish out an array larger than the string literal with '\0'.




                            Brian

                            Comment

                            • Pete Becker

                              #15
                              Re: Is this type of char array initization legal?

                              On 2008-10-24 17:17:10 -0400, "Default User" <defaultuserbr@ yahoo.comsaid:
                              Pete Becker wrote:
                              >
                              >On 2008-10-24 16:29:45 -0400, "Default User"
                              ><defaultuserbr @yahoo.comsaid:
                              >
                              >>C89's wording was similar to the C++ standard, but had further
                              >>examples to show that initialization with a string literal is
                              >>identical to a brace-enclosed list of the characters, which would
                              >>amount to the same thing.
                              >>>
                              >>
                              >So C99 made it crystal clear, presumably because C90 wasn't. <g>
                              >
                              It was, I think, clear enough. It just wasn't all put together nicely.
                              They had examples to show that:
                              >
                              char str[] = "XYZ";
                              >
                              Was equivalent to:
                              >
                              char str[] = {'X', 'Y', 'Z', '\0'};
                              >
                              So if a string literal is equivalent to a brace-enclosed list of
                              characters, then the "fewer initializer" rule would come into play to
                              finish out an array larger than the string literal with '\0'.
                              >
                              Examples in standards are not normative. That is, they do not impose
                              requirements. They illustrate what the words say. If the words don't
                              say it, examples don't make it true.

                              --
                              Pete
                              Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                              Standard C++ Library Extensions: a Tutorial and Reference
                              (www.petebecker.com/tr1book)

                              Comment

                              Working...