char array initialization

Discussion in 'C++' started by Avalon1178, Nov 9, 2007.

  1. Avalon1178

    Avalon1178 Guest

    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?
     
    Avalon1178, Nov 9, 2007
    #1
    1. Advertising

  2. 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
     
    Victor Bazarov, Nov 9, 2007
    #2
    1. Advertising

  3. Avalon1178

    Avalon1178 Guest

    On Nov 9, 1:32 pm, "Victor Bazarov" <> wrote:
    > 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
     
    Avalon1178, Nov 9, 2007
    #3
  4. Avalon1178

    Avalon1178 Guest

    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?
     
    Avalon1178, Nov 9, 2007
    #4
  5. 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
     
    Victor Bazarov, Nov 9, 2007
    #5
  6. 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 Tarasevich, Nov 10, 2007
    #6
  7. Avalon1178

    Avalon1178 Guest

    On Nov 9, 4:34 pm, Andrey Tarasevich <>
    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
     
    Avalon1178, Nov 10, 2007
    #7
  8. Avalon1178

    James Kanze Guest

    On Nov 9, 10:29 pm, 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
    > 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:
    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
     
    James Kanze, Nov 10, 2007
    #8
  9. Avalon1178

    James Kanze Guest

    On Nov 9, 11:15 pm, "Victor Bazarov" <> 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?


    > 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:
    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
     
    James Kanze, Nov 10, 2007
    #9
  10. Avalon1178

    mathieu Guest

    On 10 nov, 05:51, Avalon1178 <> wrote:
    > On Nov 9, 4:34 pm, Andrey Tarasevich <>
    > 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...
     
    mathieu, Nov 10, 2007
    #10
  11. 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.
     
    Bernd Gaertner, Nov 12, 2007
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Petter Reinholdtsen

    char array initialization: Is 'char a[] = ("a")' valid ANSI C?

    Petter Reinholdtsen, Nov 1, 2004, in forum: C Programming
    Replies:
    20
    Views:
    1,058
    Dave Thompson
    Nov 22, 2004
  2. lovecreatesbeauty
    Replies:
    1
    Views:
    1,071
    Ian Collins
    May 9, 2006
  3. Replies:
    3
    Views:
    739
  4. davidb
    Replies:
    0
    Views:
    769
    davidb
    Sep 1, 2006
  5. davidb
    Replies:
    6
    Views:
    1,560
    Default User
    Sep 1, 2006
Loading...

Share This Page