If I had to say what "arr" is, I would say it is an array of pointers
to chars. If so why is it intialized with strings instead of
addresses?

char *arr[] =
{
"a", "b", "c","dd", "eee"
};

Also when looking at the values of the pointers (when they appear to
be adjacent) they seem to decrease by at least 8 bytes ( two native
size words?) even when the strings are a single character, which
should be two bytes. So I am guessing they are on a stack if the
addresses decrease but why 8 bytes each? Is it some type of linked
list? I suppose it doesn't really matter but it is a curiosity and I
am interested in how the language works.

Thanks,

gtb

Re: Array of char pointers. by Alex

Alex
Sun Apr 13 12:27:38 CDT 2008

"goodTweetieBird" wrote:
> If I had to say what "arr" is, I would say it is an array of
> pointers to chars. If so why is it intialized with strings
> instead of addresses?

First of all, `arr' a an array of pointers to const chars. VC++
compiler allows you to assign a pointer to const char to non-const
pointer as a backward compatibility with older versions of the
compiler:

char* p = "Hello World!"; // compiles, but dangerous

// no diagnostics at compile time,
// but an access violation exception at run-time
p[3] = 'z'; // boom!

Also, you should remember that intializing a [const] pointer to
char from literal strings is no more than a courtesy of the
compiler, which is provided for developer's convenience. So, this
initialization:

const char* p = "hello";

is actually translated into this:

const char __tmp[] = { 'a', 'b', 'c', '\0' };

// array type decays to pointer type
const char* p = __tmp;

One can safely assume that `__tmp' address will stay valid for the
duration of a program because actual string data is stored in data
section of an executable image.

> char *arr[] =
> {
> "a", "b", "c","dd", "eee"
> };
>
> Also when looking at the values of the pointers (when they
> appear to be adjacent) they seem to decrease by at least 8 bytes
> ( two native size words?) even when the strings are a single
> character, which should be two bytes. So I am guessing they are
> on a stack if the addresses decrease but why 8 bytes each?

No, they aren't on stack. They're stored permanently in the data
section of an executable image. The addresses of the strings are
not required to be adjacent at all. Compiler may put them in
whatever order and at whatever locations it pleases in the data
section. Moreover, compiler may decide to coalesce similar strings
to save space, so in the following code:

const char* arr[] = { "abc", "abc", "abc" };

all three elements of the `arr' array will hold the same value:

assert(arr[0] == arr[1] == arr[2]);



> Is it some type of linked list? I suppose it doesn't really
> matter but it is a curiosity and I am interested in how the
> language works.

No, they aren't linked list or any data structure at all. Compiler
puts string literals in data section and even may enable
optimizations to save space.

HTH
Alex



Re: Array of char pointers. by Alex

Alex
Sun Apr 13 12:33:53 CDT 2008

"Alex Blekhman" wrote:
> So, this initialization:
>
> const char* p = "hello";
>
> is actually translated into this:
>
> const char __tmp[] = { 'a', 'b', 'c', '\0' };

Sorry for the type. Obviously it should be:

const char* p = "abc";


Alex



Re: Array of char pointers. by Barry

Barry
Sun Apr 13 20:57:13 CDT 2008

On Sun, 13 Apr 2008 09:25:11 -0700 (PDT), goodTweetieBird
<goodTweetieBird@hotmail.com> wrote:

>
>If I had to say what "arr" is, I would say it is an array of pointers
>to chars. If so why is it intialized with strings instead of
>addresses?
>
> char *arr[] =
> {
> "a", "b", "c","dd", "eee"
> };

It is not initialized with strings. It is initialized with the
address of strings. Each element of arr has a fixed size, probably 4
bytes but possibly 8 in a 64-bit implementation. Change your last
initialization value to "abcdefghijklmnopqrstuvb". The string would
never fit in an array element. The size of arr does not change so
obviously the strings are not in the array.

>
>Also when looking at the values of the pointers (when they appear to
>be adjacent) they seem to decrease by at least 8 bytes ( two native
>size words?) even when the strings are a single character, which
>should be two bytes. So I am guessing they are on a stack if the

String literals are rarely on the stack. The are static arrays with a
life span that begins before your program starts and continues until
it terminates. The stack is usually used only for automatic objects
and function linkage.

>addresses decrease but why 8 bytes each? Is it some type of linked
>list? I suppose it doesn't really matter but it is a curiosity and I
>am interested in how the language works.

The compiler may choose to arbitrarily align string literals on an 8
byte boundary. You should change the initialization list to something
like "1", "12", "123", "1234", "12345", ..., "123456789abcdefghijkl",
to see if this is in fact the case.


Remove del for email

Re: Array of char pointers. by goodTweetieBird

goodTweetieBird
Mon Apr 14 11:31:13 CDT 2008

On Apr 13, 9:57=A0pm, Barry Schwarz <schwa...@dqel.com> wrote:
> On Sun, 13 Apr 2008 09:25:11 -0700 (PDT), goodTweetieBird
>
> <goodTweetieB...@hotmail.com> wrote:
>
> >If I had to say what "arr" is, I would say it is an array of pointers
> >to chars. If so why is it intialized with strings instead of
> >addresses?
>
> > =A0 =A0char *arr[] =3D
> > =A0 =A0{
> > =A0 =A0 =A0 =A0 =A0 =A0"a", "b", "c","dd", "eee"
> > =A0 =A0};
>
> It is not initialized with strings. =A0It is initialized with the
> address of strings.

I misspoke, I should have said why does it appear to be initialized
with strings as I am providing strings and not addresses. But you
figured out what I meant.

Instead of

char *arr[] =3D

should I write

char const *arr[] =3D

?



Re: Array of char pointers. by David

David
Mon Apr 14 11:46:55 CDT 2008

goodTweetieBird wrote:
> I misspoke, I should have said why does it appear to be initialized
> with strings as I am providing strings and not addresses. But you
> figured out what I meant.
>
> Instead of
>
> char *arr[] =
>
> should I write
>
> char const *arr[] =


gtb:

Yes, or

const char *arr[] =

(they are the same).

--
David Wilkinson
Visual C++ MVP

Re: Array of char pointers. by Barry

Barry
Mon Apr 14 21:00:50 CDT 2008

On Mon, 14 Apr 2008 09:31:13 -0700 (PDT), goodTweetieBird
<goodTweetieBird@hotmail.com> wrote:

>On Apr 13, 9:57 pm, Barry Schwarz <schwa...@dqel.com> wrote:
>> On Sun, 13 Apr 2008 09:25:11 -0700 (PDT), goodTweetieBird
>>
>> <goodTweetieB...@hotmail.com> wrote:
>>
>> >If I had to say what "arr" is, I would say it is an array of pointers
>> >to chars. If so why is it intialized with strings instead of
>> >addresses?
>>
>> >    char *arr[] =
>> >    {
>> >            "a", "b", "c","dd", "eee"
>> >    };
>>
>> It is not initialized with strings.  It is initialized with the
>> address of strings.
>
>I misspoke, I should have said why does it appear to be initialized
>with strings as I am providing strings and not addresses. But you
>figured out what I meant.
>
>Instead of
>
> char *arr[] =
>
>should I write
>
> char const *arr[] =

If the elements of arr will always point to sting literals, then the
const modifier is appropriate. String literals are not modifiable and
the const modifier compels the compiler to issue a diagnostic if you
try to change any part of them.

However, the const modifier is completely unrelated to your question.
It only appears you are initializing the array with strings. Each of
the string literals is actually an array. In this context, an
expression of array type is converted to the address of the first
array element with type pointer to element. So the "a" is actually an
array of two char ('a' and '\0') which is evaluated as the address of
the 'a' with type char*. This is exactly the type that should be
assigned to arr[0].


Remove del for email

Re: Array of char pointers. by Ben

Ben
Tue Apr 15 18:01:45 CDT 2008

>> Instead of
>>
>> char *arr[] =
>>
>> should I write
>>
>> char const *arr[] =
>
> If the elements of arr will always point to sting literals, then the
> const modifier is appropriate. String literals are not modifiable and
> the const modifier compels the compiler to issue a diagnostic if you
> try to change any part of them.
>
> However, the const modifier is completely unrelated to your question.
> It only appears you are initializing the array with strings. Each of
> the string literals is actually an array. In this context, an
> expression of array type is converted to the address of the first
> array element with type pointer to element. So the "a" is actually an
> array of two char ('a' and '\0') which is evaluated as the address of
> the 'a' with type char*. This is exactly the type that should be
> assigned to arr[0].

"a" is an array of readonly char. It's not "const char" exactly, to avoid
breaking programs written before const existed, but it will be in a readonly
data area and attempting to use it in a non-const way will break horribly.

New code should always use const whenever you make a pointer to a string
literal.

>
>
> Remove del for email



Re: Array of char pointers. by Hendrik

Hendrik
Tue Apr 15 19:08:23 CDT 2008

Ben Voigt [C++ MVP] <rbv@nospam.nospam> wrote:
> [...]
> "a" is an array of readonly char. It's not "const char" exactly, to avoid
> breaking programs written before const existed [...]

Acutally, it is 'const char[], but there's a (deprecated)
implicit conversion to 'char*' in order to keep old code
compiling.

> New code should always use const whenever you make a pointer to a string
> literal.

Ack.

Schobi

--
SpamTrap@gmx.de is never read
I'm HSchober at gmx dot de
"The trouble with being a god is that you've got
no one to pray to." Terry Pratchett



Re: Array of char pointers. by Barry

Barry
Wed Apr 16 20:52:51 CDT 2008

On Tue, 15 Apr 2008 18:01:45 -0500, "Ben Voigt [C++ MVP]"
<rbv@nospam.nospam> wrote:

>>> Instead of
>>>
>>> char *arr[] =
>>>
>>> should I write
>>>
>>> char const *arr[] =
>>
>> If the elements of arr will always point to sting literals, then the
>> const modifier is appropriate. String literals are not modifiable and
>> the const modifier compels the compiler to issue a diagnostic if you
>> try to change any part of them.
>>
>> However, the const modifier is completely unrelated to your question.
>> It only appears you are initializing the array with strings. Each of
>> the string literals is actually an array. In this context, an
>> expression of array type is converted to the address of the first
>> array element with type pointer to element. So the "a" is actually an
>> array of two char ('a' and '\0') which is evaluated as the address of
>> the 'a' with type char*. This is exactly the type that should be
>> assigned to arr[0].
>
>"a" is an array of readonly char. It's not "const char" exactly, to avoid
>breaking programs written before const existed, but it will be in a readonly
>data area and attempting to use it in a non-const way will break horribly.
>
>New code should always use const whenever you make a pointer to a string
>literal.

Not if his code he contains lines like
char x[] = "abc";
arr[0] = x;

Like I said in the beginning, const is appropriate only if all the
elements of arr always point to non-modifiable data.


Remove del for email

Re: Array of char pointers. by Ben

Ben
Thu Apr 17 09:54:42 CDT 2008

>> New code should always use const whenever you make a pointer to a
>> string literal.
>
> Not if his code he contains lines like
> char x[] = "abc";
> arr[0] = x;
>
> Like I said in the beginning, const is appropriate only if all the
> elements of arr always point to non-modifiable data.

That snippet doesn't make a pointer to a string literal. It initializes an
array in writable memory. There's a big difference.

I stand by the correctness and universal applicability of my earlier rule.

>
>
> Remove del for email



Re: Array of char pointers. by Barry

Barry
Thu Apr 17 20:36:55 CDT 2008

On Thu, 17 Apr 2008 09:54:42 -0500, "Ben Voigt [C++ MVP]"
<rbv@nospam.nospam> wrote:

>>> New code should always use const whenever you make a pointer to a
>>> string literal.
>>
>> Not if his code he contains lines like
>> char x[] = "abc";
>> arr[0] = x;
>>
>> Like I said in the beginning, const is appropriate only if all the
>> elements of arr always point to non-modifiable data.
>
>That snippet doesn't make a pointer to a string literal. It initializes an
>array in writable memory. There's a big difference.
>
>I stand by the correctness and universal applicability of my earlier rule.

So how does your rule deal with

int main(void)
{
char *arr[] = {"a", "bc", "def", "ghij"};
char var[] = "variable text";
int i;
if (i = function_that_decides_predefined_text_is_inappropriate())
{
if (i > 0)
{
var[7] = 'q';
var[8] = '\0';
}
else
{
var[3] = 'y';
var[4] = '\0';
}
arr[0] = var;
}
for (i = 0; i < 4; i++)
puts(arr[i]);
return 0;
}

My only point is that just because a pointer starts out pointing to a
string literal does not mean it will always point to one.


Remove del for email

Re: Array of char pointers. by Tamas

Tamas
Fri Apr 18 20:05:06 CDT 2008

Barry Schwarz wrote:

> My only point is that just because a pointer starts out pointing to a
> string literal does not mean it will always point to one.

As long as a single item in your array points to a string literal, you
should make the entire array const. In your code it is difficult to tell
which items are safe to be changed.

Here's a shorter example:

char var[] = "variable text";
const char *arr[] = {"a", "bc", var, "ghij"};

You are right that

arr[2][0] = 'X'

could be legal, but is it safe? Not really, because

arr[1][0] = 'X'

exhibits undefined behavior.

Please use const in `arr'. If you have to modify `var', you can still do
it, even if `arr' is const:

var[0] = 'X'; // <- fine, even though `arr' is const
puts(arr[2]); // prints "Xariable text"

Tom

Re: Array of char pointers. by Ben

Ben
Mon Apr 21 11:11:38 CDT 2008

Barry Schwarz wrote:
> On Thu, 17 Apr 2008 09:54:42 -0500, "Ben Voigt [C++ MVP]"
> <rbv@nospam.nospam> wrote:
>
>>>> New code should always use const whenever you make a pointer to a
>>>> string literal.
>>>
>>> Not if his code he contains lines like
>>> char x[] = "abc";
>>> arr[0] = x;
>>>
>>> Like I said in the beginning, const is appropriate only if all the
>>> elements of arr always point to non-modifiable data.
>>
>> That snippet doesn't make a pointer to a string literal. It
>> initializes an array in writable memory. There's a big difference.
>>
>> I stand by the correctness and universal applicability of my earlier
>> rule.
>
> So how does your rule deal with
>
> int main(void)
> {
> char *arr[] = {"a", "bc", "def", "ghij"};
> char var[] = "variable text";
> int i;
> if (i = function_that_decides_predefined_text_is_inappropriate())
> {
> if (i > 0)
> {
> var[7] = 'q';
> var[8] = '\0';
> }
> else
> {
> var[3] = 'y';
> var[4] = '\0';
> }
> arr[0] = var;
> }
> for (i = 0; i < 4; i++)
> puts(arr[i]);
> return 0;
> }

By changing the type of arr to:

const char *arr[] = { ... };

Which is as it should be.

>
> My only point is that just because a pointer starts out pointing to a
> string literal does not mean it will always point to one.

Then it's a polymorphic pointer. char* is a subtype of const char*, if your
collection can contain either then it should be defined using the supertype
as only the operations allowed on the supertype are safe.

>
>
> Remove del for email