char array initialization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Avalon1178

    #1

    char array initialization

    During a review of one of my peer's code, I ran into a section of code
    that was a bit suprising to me. Its got to do with initialization of
    a variable-length array. I ran a small application to convince myself
    whether it works or not, and it does work---however I couldn't explain
    it to myself why, so I thought I'd ask here.

    The sample code is below:

    char test[] = "hello world\n"; // test string, but I could easily
    have retrieved this string from a file or wherever
    int len = strlen(test)+1;
    // line below is the code of interest
    char out[len];
    strncpy(out, test, len);
    printf("out: %s", out);

    Note that 'out' is declared on the stack, yet 'len' is a variable
    whose value is not known at compile time. Why would this work? I
    would think the proper way of instantiating a char array with variable
    length is using new, like "char *out = new char[len]", yet somehow the
    above code works. Can someone explain why this works?

  • Victor Bazarov

    #2
    Re: char array initialization

    Avalon1178 wrote:
    During a review of one of my peer's code, I ran into a section of code
    that was a bit suprising to me. Its got to do with initialization of
    a variable-length array. I ran a small application to convince myself
    whether it works or not, and it does work---however I couldn't explain
    it to myself why, so I thought I'd ask here.
    >
    The sample code is below:
    >
    char test[] = "hello world\n"; // test string, but I could easily
    have retrieved this string from a file or wherever
    What do you mean, "retrieve from a file"? By including some text with
    the string defined as a macro? It doesn't make this string "variable-
    length".
    int len = strlen(test)+1;
    // line below is the code of interest
    char out[len];
    That's illegal in C++.
    strncpy(out, test, len);
    printf("out: %s", out);
    >
    Note that 'out' is declared on the stack, yet 'len' is a variable
    whose value is not known at compile time. Why would this work?
    Because the compiler with which it is compiled offered this syntax
    as an extension, most likely.
    I
    would think the proper way of instantiating a char array with variable
    length is using new, like "char *out = new char[len]", yet somehow the
    above code works. Can someone explain why this works?
    It's not legal C++. It works because the compiler wasn't compiling
    C++, it was compiling "C++ with extensions".

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


    Comment

    • Avalon1178

      #3
      Re: char array initialization

      On Nov 9, 1:32 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
      Avalon1178 wrote:
      During a review of one of my peer's code, I ran into a section of code
      that was a bit suprising to me. Its got to do with initialization of
      a variable-length array. I ran a small application to convince myself
      whether it works or not, and it does work---however I couldn't explain
      it to myself why, so I thought I'd ask here.
      >
      The sample code is below:
      >
      char test[] = "hello world\n"; // test string, but I could easily
      have retrieved this string from a file or wherever
      >
      What do you mean, "retrieve from a file"? By including some text with
      the string defined as a macro? It doesn't make this string "variable-
      length".
      I'm just saying that 'test' could have been set or initialized
      anywhere, and not necessary like the one I defined above (i.e. like
      getline(), or snprintf, or whatever). I just did it for simple
      demonstration.
      >
      int len = strlen(test)+1;
      // line below is the code of interest
      char out[len];
      >
      That's illegal in C++.
      >
      Yeah, that's what I thought too....
      strncpy(out, test, len);
      printf("out: %s", out);
      >
      Note that 'out' is declared on the stack, yet 'len' is a variable
      whose value is not known at compile time. Why would this work?
      >
      Because the compiler with which it is compiled offered this syntax
      as an extension, most likely.
      >
      I
      would think the proper way of instantiating a char array with variable
      length is using new, like "char *out = new char[len]", yet somehow the
      above code works. Can someone explain why this works?
      >
      It's not legal C++. It works because the compiler wasn't compiling
      C++, it was compiling "C++ with extensions".
      >
      Great! Thanks for the explanation.
      V
      --
      Please remove capital 'A's when replying by e-mail
      I do not respond to top-posted replies, please don't ask

      Comment

      • Avalon1178

        #4
        Re: char array initialization

        Hmm.....so I gather it is compiler dependent. I compiled the code
        using g++, and after doing g++ -v, here's the version it is running:

        Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.6/specs
        Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
        infodir=/usr/share/info --enable-shared --enable-threads=posix --
        disable-checking --with-system-zlib --enable-__cxa_atexit --disable-
        libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
        Thread model: posix
        gcc version 3.4.6 20060404 (Red Hat 3.4.6-3)

        I'm still curious however....if say I am using this C++ with
        extensions, how exactly is the compiler generating the assembly code
        for 'char out[len]', since the compiled binary is working?

        Comment

        • Victor Bazarov

          #5
          Re: char array initialization

          Avalon1178 wrote:
          [..]
          I'm still curious however....if say I am using this C++ with
          extensions, how exactly is the compiler generating the assembly code
          for 'char out[len]', since the compiled binary is working?
          I am unclear what it is you'd like to know. If you want to see how
          compilers generate assembly, you need to look into the compiler's
          source code. Beyond that, why do you care how they do it? Magic,
          would be my guess. Also, try asking in 'comp.compilers '.

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


          Comment

          • Andrey Tarasevich

            #6
            Re: char array initialization

            Avalon1178 wrote:
            ...
            I'm still curious however....if say I am using this C++ with
            extensions, how exactly is the compiler generating the assembly code
            for 'char out[len]', since the compiled binary is working?
            ...
            Have you ever heard of 'alloca' function? It allocates memory in the
            stack, which then gets automatically deallocated when function exits.
            (It is not a part of the standard C or C++ library).

            That's pretty much how the compiler extension in question works. When
            you write something like

            char out[len];

            where 'len' is a run-time value, the compiler actually generates
            something like

            char* out = alloca(len);

            i.e. internally your 'out' is actually a pointer, not an array. That's it.

            Of course, the full functionality of this extension is more complicated
            than that. It has to provide proper C++ lifetime for the array and its
            elements (which might end before the function returns), call the
            constructors and destructors, make the 'sizeof' to see it as an array,
            not a pointer, and so on. But the general memory management idea is not
            much different from what is illustrated above.

            --
            Best regards,
            Andrey Tarasevich

            Comment

            • Avalon1178

              #7
              Re: char array initialization

              On Nov 9, 4:34 pm, Andrey Tarasevich <andreytarasev. ..@hotmail.com>
              wrote:
              Avalon1178 wrote:
              ...
              I'm still curious however....if say I am using this C++ with
              extensions, how exactly is the compiler generating the assembly code
              for 'char out[len]', since the compiled binary is working?
              ...
              >
              Have you ever heard of 'alloca' function? It allocates memory in the
              stack, which then gets automatically deallocated when function exits.
              (It is not a part of the standard C or C++ library).
              >
              That's pretty much how the compiler extension in question works. When
              you write something like
              >
              char out[len];
              >
              where 'len' is a run-time value, the compiler actually generates
              something like
              >
              char* out = alloca(len);
              >
              i.e. internally your 'out' is actually a pointer, not an array. That's it.
              >
              Of course, the full functionality of this extension is more complicated
              than that. It has to provide proper C++ lifetime for the array and its
              elements (which might end before the function returns), call the
              constructors and destructors, make the 'sizeof' to see it as an array,
              not a pointer, and so on. But the general memory management idea is not
              much different from what is illustrated above.
              >
              --
              Best regards,
              Andrey Tarasevich
              Andrey,

              No, I've never heard of alloca() but thanks a lot for the
              information! I really appreciate it.

              Avalon1178

              Comment

              • James Kanze

                #8
                Re: char array initialization

                On Nov 9, 10:29 pm, Avalon1178 <Avalon1...@gma il.comwrote:
                During a review of one of my peer's code, I ran into a section of code
                that was a bit suprising to me. Its got to do with initialization of
                a variable-length array. I ran a small application to convince myself
                whether it works or not, and it does work---however I couldn't explain
                it to myself why, so I thought I'd ask here.
                The sample code is below:
                char test[] = "hello world\n"; // test string, but I could easily
                have retrieved this string from a file or wherever
                int len = strlen(test)+1;
                // line below is the code of interest
                char out[len];
                strncpy(out, test, len);
                printf("out: %s", out);
                Note that 'out' is declared on the stack, yet 'len' is a variable
                whose value is not known at compile time. Why would this work?
                It doesn't, at least not in C++. You may have activated some
                local extension, or be compiling in C.
                I would think the proper way of instantiating a char array
                with variable length is using new, like "char *out = new
                char[len]", yet somehow the above code works. Can someone
                explain why this works?
                It doesn't compiler with any of the compilers I use, at least
                when I invoke them with the necessary options for them to
                compile C++. None of the compilers are really C++ compilers if
                just invoked without options. At the very least, for example,
                g++ requires -std=c++98, VC++ requires things like /Ehs /GR
                (from memory, I don't have a machine with the compiler handy at
                the moment), and so on.

                --
                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

                • James Kanze

                  #9
                  Re: char array initialization

                  On Nov 9, 11:15 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
                  Avalon1178 wrote:
                  [..]
                  I'm still curious however....if say I am using this C++ with
                  extensions, how exactly is the compiler generating the assembly code
                  for 'char out[len]', since the compiled binary is working?
                  I am unclear what it is you'd like to know. If you want to see how
                  compilers generate assembly, you need to look into the compiler's
                  source code. Beyond that, why do you care how they do it? Magic,
                  would be my guess. Also, try asking in 'comp.compilers '.
                  Just a guess, but it's probably doing the same thing the C
                  compiler does---his code was purely legal C.

                  There are two possible solutions: on many systems, it's possible
                  to just grab a hunk of the stack---on an Intel, "sub sp,N" will
                  do the trick. In cases where that doesn't work, there's nothing
                  to prevent the compiler from generating a call to malloc, with a
                  call to free on leaving the block.

                  --
                  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

                  • mathieu

                    #10
                    Re: char array initialization

                    On 10 nov, 05:51, Avalon1178 <Avalon1...@gma il.comwrote:
                    On Nov 9, 4:34 pm, Andrey Tarasevich <andreytarasev. ..@hotmail.com>
                    wrote:
                    >
                    >
                    >
                    Avalon1178 wrote:
                    ...
                    I'm still curious however....if say I am using this C++ with
                    extensions, how exactly is the compiler generating the assembly code
                    for 'char out[len]', since the compiled binary is working?
                    ...
                    >
                    Have you ever heard of 'alloca' function? It allocates memory in the
                    stack, which then gets automatically deallocated when function exits.
                    (It is not a part of the standard C or C++ library).
                    >
                    That's pretty much how the compiler extension in question works. When
                    you write something like
                    >
                    char out[len];
                    >
                    where 'len' is a run-time value, the compiler actually generates
                    something like
                    >
                    char* out = alloca(len);
                    >
                    i.e. internally your 'out' is actually a pointer, not an array. That's it.
                    >
                    Of course, the full functionality of this extension is more complicated
                    than that. It has to provide proper C++ lifetime for the array and its
                    elements (which might end before the function returns), call the
                    constructors and destructors, make the 'sizeof' to see it as an array,
                    not a pointer, and so on. But the general memory management idea is not
                    much different from what is illustrated above.
                    >
                    --
                    Best regards,
                    Andrey Tarasevich
                    >
                    Andrey,
                    >
                    No, I've never heard of alloca() but thanks a lot for the
                    information! I really appreciate it.
                    Hi Avalon1178,

                    When using gcc, you can use the -pedantic (use very carefully). It
                    will shows you whether your code is C++ compliant or not.

                    HTH
                    -Mahtieu
                    Ps: of course you also need to keep your -W -Wall falsg too...


                    Comment

                    • Bernd Gaertner

                      #11
                      Re: char array initialization

                      Avalon1178 wrote:
                      char test[] = "hello world\n"; // test string, but I could easily
                      have retrieved this string from a file or wherever
                      int len = strlen(test)+1;
                      // line below is the code of interest
                      char out[len];
                      strncpy(out, test, len);
                      printf("out: %s", out);
                      >
                      Note that 'out' is declared on the stack, yet 'len' is a variable
                      whose value is not known at compile time. Why would this work? I
                      would think the proper way of instantiating a char array with variable
                      length is using new, like "char *out = new char[len]", yet somehow the
                      above code works. Can someone explain why this works?
                      >
                      Some compilers (I know of g++) extend the standard to allow
                      variable-length arrays (the reason being that this is allowed in C, and
                      it wouldn't make sense to disable it for C++). But the resulting code is
                      not portable, of course.

                      Bernd.

                      Comment

                      Working...