extern const char * vs. extern const char []http://tinyurl.com/47e3k

T

Thomas Matthews

Hi,

I'm puzzled over the difference between:
extern const char *
and
extern const char [].
My understanding is that the two are equivalent,
but the program below shows elsewise.

Given the simple program below:
// File names.cpp
extern const char Hello_Text[] = "Hello";
extern const char World_Text[] = "World!";

// File main.cpp
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;

template <const char * name>
void print_text(void) // personal pref. here
{
cout << name << endl;
return;
}

/* Refer to variables in names.cpp */
/* Note declaration of char * here */
/* versus char [] in names.cpp. */
extern const char * Hello_Text;
extern const char * World_Text;

int main(void)
{
cout << "Start of Test" << endl;
print_text<Hello_Text>();
print_text<World_Text>();
cout << "End of Test" << endl;
return EXIT_SUCCESS;
}

When compiled with Gnu G++ 3.3.1, I get the following
error message (line numbers omitted):
$ g++ -o main.cpp extern_names.cpp
In function `int main()':
error: `Hello_Text' is not a valid template argument
it must be the address of an object with
external linkage
no matching function for call to
`print_text()'
error: `World_Text' is not a valid template argument
it must be the address of an object with
external linkage
no matching function for call to
`print_text()'

I know that the following two statments are different:
(1) extern const char text[] = "Hello";
(2) extern const char * text = "Hello";
because (1) allocates an array of 6 locations and
(2) creates a pointer to a 'C' string literal.

But because the variable 'text' above in (1) is an
array and it has a location, a pointer can be created
and assigned to the location of the first character.
So, I would expect that
extern const char * text;
would be a pointer that refers to the start of the
character array, much the same as this statment:
extern const char text[];

So why are they different when used as template
parameters?

Does Chris Torek's "The Rule" apply here?
http://web.torek.net/torek/c/pa.html

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
A

Alf P. Steinbach

* Thomas Matthews:
I'm puzzled over the difference between:
extern const char *
and
extern const char [].
My understanding is that the two are equivalent,
but the program below shows elsewise.

The first is a pointer, the second is an array.

An array can decay to a pointer e.g. when used as an argument or
in an assignment, and a pointer can be used syntactically like an
array, and vice versa (due to the decay to pointer, an automatic
&a[0] supplied by the compiler, wherever necessary).

But it's not the same thing at all; in particular an array can
and usually will occupy much more storage than a pointer.
 
V

Victor Bazarov

Alf P. Steinbach said:
* Thomas Matthews:
I'm puzzled over the difference between:
extern const char *
and
extern const char [].
My understanding is that the two are equivalent,
but the program below shows elsewise.

The first is a pointer, the second is an array.

An array can decay to a pointer e.g. when used as an argument or
in an assignment, and a pointer can be used syntactically like an
array, and vice versa (due to the decay to pointer, an automatic
&a[0] supplied by the compiler, wherever necessary).

But it's not the same thing at all; in particular an array can
and usually will occupy much more storage than a pointer.

Which is a bit misleading, Alf. In the case of an extern const char
it is more likely used for some non-changing C-string, in which case
the array will be allocated of the size to store only the characters
in the initialising literal, while with a pointer the compiler will
have to allocate yet additional 4 bytes for the pointer itself. Yes,
the array is larger than a pointer, but one always must look at the
whole picture. The pointer has to point somewhere, and that is some
additional storage. So the fact that an array itself is larger than
a single pointer plays really no role.

Victor
 
?

=?ISO-8859-2?Q?Mateusz_=A3oskot?=

But it's not the same thing at all; in particular an array can
and usually will occupy much more storage than a pointer.

I'd like to add one thing.
All this pointer<->array (first element) "conversion" is not explicit.

Greets
 
A

Alf P. Steinbach

* Victor Bazarov:
Alf P. Steinbach said:
* Thomas Matthews:
I'm puzzled over the difference between:
extern const char *
and
extern const char [].
My understanding is that the two are equivalent,
but the program below shows elsewise.

The first is a pointer, the second is an array.

An array can decay to a pointer e.g. when used as an argument or
in an assignment, and a pointer can be used syntactically like an
array, and vice versa (due to the decay to pointer, an automatic
&a[0] supplied by the compiler, wherever necessary).

But it's not the same thing at all; in particular an array can
and usually will occupy much more storage than a pointer.

Which is a bit misleading, Alf. In the case of an extern const char
it is more likely used for some non-changing C-string, in which case
the array will be allocated of the size to store only the characters
in the initialising literal, while with a pointer the compiler will
have to allocate yet additional 4 bytes for the pointer itself. Yes,
the array is larger than a pointer, but one always must look at the
whole picture. The pointer has to point somewhere, and that is some
additional storage.

Yep, agreed.

So the fact that an array itself is larger than a single pointer plays
really no role.

It does in this context; I was talking about interchangability.

They're not interchangable declarations, which is most easily seen from
the fact that they denote objects of usually different memory sizes.

The problem is that with many compilers+linkers using one where the
other should be can compile and link, but gives a non-functioning program.
 
T

tom_usenet

Hi,

I'm puzzled over the difference between:
extern const char *
and
extern const char [].
My understanding is that the two are equivalent,
but the program below shows elsewise.

Given the simple program below:
// File names.cpp
extern const char Hello_Text[] = "Hello";
extern const char World_Text[] = "World!";

// File main.cpp
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;

template <const char * name>
void print_text(void) // personal pref. here
{
cout << name << endl;
return;
}

/* Refer to variables in names.cpp */
/* Note declaration of char * here */
/* versus char [] in names.cpp. */
extern const char * Hello_Text;
extern const char * World_Text;

int main(void)
{
cout << "Start of Test" << endl;
print_text<Hello_Text>();
print_text<World_Text>();
cout << "End of Test" << endl;
return EXIT_SUCCESS;
}

When compiled with Gnu G++ 3.3.1, I get the following
error message (line numbers omitted):
$ g++ -o main.cpp extern_names.cpp
In function `int main()':
error: `Hello_Text' is not a valid template argument
it must be the address of an object with
external linkage
no matching function for call to
`print_text()'
error: `World_Text' is not a valid template argument
it must be the address of an object with
external linkage
no matching function for call to
`print_text()'

I know that the following two statments are different:
(1) extern const char text[] = "Hello";
(2) extern const char * text = "Hello";
because (1) allocates an array of 6 locations and
(2) creates a pointer to a 'C' string literal.

But because the variable 'text' above in (1) is an
array and it has a location, a pointer can be created
and assigned to the location of the first character.
So, I would expect that
extern const char * text;
would be a pointer that refers to the start of the
character array, much the same as this statment:
extern const char text[];

So why are they different when used as template
parameters?

You have two different problems here. Firstly, with pointer template
parameters, you must either explicitly or implicitly pass the address
of an object with external linkage. Above, you're trying to pass an
object with external linkage itself rather than its address.

Secondly, even if it did compile you've got a linker error (although
it isn't required to be diagnosed, and it will link successfully on
many platforms) since your const char* is a different type from the
extern variables in the other TU - you need const char[] as the type
(which is an incomplete type). Declarations of arrays are allowed to
differ in the size of the last array bound, but not in whether they
are an array or pointer.

Tom
 

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

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top