char array initialization

A

Avalon1178

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

Victor Bazarov

Avalon1178 said:
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
 
A

Avalon1178

Avalon1178 said:
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.
 
A

Avalon1178

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

Victor Bazarov

Avalon1178 said:
[..]
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
 
A

Andrey Tarasevich

Avalon1178 said:
...
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.
 
A

Avalon1178

Avalon1178 said:
...
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.

Andrey,

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

Avalon1178
 
J

James Kanze

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

James Kanze

Avalon1178 said:
[..]
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.
 
M

mathieu

Avalon1178 said:
...
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.

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

Bernd Gaertner

Avalon1178 said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top