By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 1,997 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

char array initialization

P: n/a
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?

Nov 9 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
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
Nov 9 '07 #2

P: n/a
On Nov 9, 1:32 pm, "Victor Bazarov" <v.Abaza...@comAcast.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

Nov 9 '07 #3

P: n/a
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?

Nov 9 '07 #4

P: n/a
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
Nov 9 '07 #5

P: n/a
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
Nov 10 '07 #6

P: n/a
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

Nov 10 '07 #7

P: n/a
On Nov 9, 10:29 pm, Avalon1178 <Avalon1...@gmail.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:ja*********@gmail.com
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
Nov 10 '07 #8

P: n/a
On Nov 9, 11:15 pm, "Victor Bazarov" <v.Abaza...@comAcast.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:ja*********@gmail.com
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

Nov 10 '07 #9

P: n/a
On 10 nov, 05:51, Avalon1178 <Avalon1...@gmail.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...
Nov 10 '07 #10

P: n/a
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.
Nov 12 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.