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

Discussion in 'C++' started by Thomas Matthews, Jul 31, 2004.

  1. 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
    Thomas Matthews, Jul 31, 2004
    #1
    1. Advertising

  2. * 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jul 31, 2004
    #2
    1. Advertising

  3. "Alf P. Steinbach" <> wrote...
    > * 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
    Victor Bazarov, Jul 31, 2004
    #3
  4. On 7/31/2004 5:46 PM, Alf P. Steinbach wrote:
    > 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
    --

    Mateusz £oskot
    mateusz at loskot dot net
    =?ISO-8859-2?Q?Mateusz_=A3oskot?=, Jul 31, 2004
    #4
  5. * Victor Bazarov:
    > "Alf P. Steinbach" <> wrote...
    > > * 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jul 31, 2004
    #5
  6. Thomas Matthews

    tom_usenet Guest

    On Sat, 31 Jul 2004 15:35:48 GMT, Thomas Matthews
    <> wrote:

    >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
    tom_usenet, Aug 2, 2004
    #6
    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. dorayme

    tinyURL address for how long?

    dorayme, May 31, 2006, in forum: HTML
    Replies:
    56
    Views:
    12,593
    Mark Parnell
    Jun 5, 2006
  2. Replies:
    24
    Views:
    827
    Netocrat
    Oct 30, 2005
  3. lovecreatesbeauty
    Replies:
    1
    Views:
    1,043
    Ian Collins
    May 9, 2006
  4. Javier
    Replies:
    2
    Views:
    559
    James Kanze
    Sep 4, 2007
  5. Vincent Foley

    TinyUrl class

    Vincent Foley, Jun 1, 2005, in forum: Ruby
    Replies:
    6
    Views:
    177
    Dominik Bathon
    Jun 2, 2005
Loading...

Share This Page