char* and char

Y

Ying Yang

Hi,

whats the difference between:

char* a = new char;

char* b = new char[10];

char c [10];


Regards
BN
 
D

David White

Ying Yang said:
Hi,

whats the difference between:

char* a = new char;

char* b = new char[10];

'a' and 'b' are both pointers to a char. That is, they each contain the
address in memory of a char. In the case of 'b', there happens to be another
9 chars after the first one, but it is up to the programmer to be aware of
that (including using "delete[]" for 'b' and just "delete" for 'a' later
when you delete them). Once created, the compiler treats both pointers the
same.
char c [10];

'c' is an array of 10 chars. If you use 'c' where a char * is expected, the
compiler will create the char * by taking the address of the first char in
the array. But 'c' itself is an array, not a pointer, so it is a different
type from 'a' and 'b'.

DW
 
A

Attila Feher

Ying said:
Hi,

whats the difference between:

char* a = new char;

"a" is a pointer to a character, initialized by the expression new char.
The expression new char allocates memory for one character from the free
store and (according to the current wording of the standard) initialized it
by doing nothing. So "a" will point at that "random" character in the free
store (sometimes called heap).

If new char cannot allocate memory for one object of type char it will throw
an std::bad_alloc exception, which will be either caught by an appropriate
ctach-handler or will cause the system to call a function named terminate(),
which will by default call a function named abort() and that one will stop
the programs' execution.
char* b = new char[10];

"b" is a pointer to a character, initialized by the expression new char[10].
The expression new char[10] allocates a block of continuous memory for 10
character from the free store and (according to the current wording of the
standard) initialized it by doing nothing. After initialization "b" will
point at the first of those 10 "random" characters in the free store
(sometimes called heap).

Rest is the same as before.
char c [10];

This one can be many things. So let's skip initialization and meaning
(because it can be namespace scope or automatic or member declaration) and
let's just go for the type.

"c" is an array of 10 characters. This means that it has the type: array of
10 characters. When using "c" in certain expressions it will (so-called)
decay into a pointer to the first element of that array. In such a case it
will behave much like "b" before, except that the memory area belonging to
"c" is not necessarily from the free-store:

c[2]; // third element of c
b[2]; // third element of b

It is important to note that while many many times "c" will behave as a
pointer to the first element of the array it represents, it is not one. It
just can behave as one (in certain expressions) for our convenience.
 
D

Default User

David said:
'c' is an array of 10 chars. If you use 'c' where a char * is expected, the
compiler will create the char * by taking the address of the first char in
the array.

Except for a few well-documented cases, such as when used with the
sizeof and address-of (&) operators.




Brian Rodenborn
 
K

Karl Heinz Buchegger

Ying said:
Hi,

whats the difference between:

char* a = new char;


a
+-------+ +---+
| o------------------>| |
+-------+ +---+
char* b = new char[10];

b
+-------+ +---+---+---+---+---+---+---+---+---+---+
| o------------------>| | | | | | | | | | |
+-------+ +---+---+---+---+---+---+---+---+---+---+
char c [10];

c
+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+

HTH
 
D

David White

Default User said:
Except for a few well-documented cases, such as when used with the
sizeof and address-of (&) operators.

But neither of these cases is using 'c' where a char * is expected, is it?

DW
 
K

Kevin Goodsell

David said:
'c' is an array of 10 chars. If you use 'c' where a char * is expected, the
compiler will create the char * by taking the address of the first char in
the array.

A stronger statement is called for here. If you use 'c' for any purpose
other than as the operand for the address-of or sizeof operator, the
compiler will convert it to char*. It does not have to occur in a
context that calls for a char*.

-Kevin
 
W

White Wolf

Kevin said:
A stronger statement is called for here. If you use 'c' for any
purpose other than as the operand for the address-of or sizeof
operator, the compiler will convert it to char*. It does not have to
occur in a
context that calls for a char*.

Not exactly. Template argument deduction will not (AFAIK) decay it into a
pointer.
 
K

Kevin Goodsell

White said:
Not exactly. Template argument deduction will not (AFAIK) decay it into a
pointer.

Good point. In C what I said holds true, but I was never very sure if
C++ added other contexts where the "decay to pointer" would be bypassed.
No one bothered to point this out until now, and it simply never
occurred to me.

-Kevin
 
D

Default User

David said:
But neither of these cases is using 'c' where a char * is expected, is it?


I'm pointing out the cases where no conversion takes place. Many people
are unaware of these exceptions, you'll often see the phrase, "the name
of the array is a pointer to the first element". Naturally, the
operators mentioned take any type.



Brian Rodenborn
 
D

Default User

Kevin said:
Good point. In C what I said holds true, but I was never very sure if
C++ added other contexts where the "decay to pointer" would be bypassed.
No one bothered to point this out until now, and it simply never
occurred to me.


I wasn't either, so I hedged my bets :)

I'm not as strong on templates as I should be, I wasn't sure if you
could instantiate with array types or not. They'd be tricky, because any
resulting variables in a class would not be modifiable lvalues and all
that.



Brian Rodenborn
 
W

White Wolf

Default said:
I wasn't either, so I hedged my bets :)

I'm not as strong on templates as I should be, I wasn't sure if you
could instantiate with array types or not. They'd be tricky, because
any resulting variables in a class would not be modifiable lvalues
and all that.

Really? How come? What do you mean by that?
 
D

David White

Kevin Goodsell said:
A stronger statement is called for here. If you use 'c' for any purpose
other than as the operand for the address-of or sizeof operator, the
compiler will convert it to char*. It does not have to occur in a
context that calls for a char*.

Perhaps this is a bit too strong. It's liable to cause some people to think
of an array more as a pointer than as an array.

What about
char ch = c;
?
Is this using 'c' as an array or a pointer? The result is the same whether
'c' is an array or a pointer, but I'd prefer to think of the pointer case as
behaving like an array than the array case behaving like a pointer.

What happens to the array here?
struct S
{
char c[10];
};

void f(S &s1, S &s2)
{
s1 = s2;
}

There's no pointer behaviour in this case.

I think it's better to list the cases where one type decays to another than
to list the exceptions.

DW
 
W

White Wolf

David said:
Perhaps this is a bit too strong. It's liable to cause some people to
think of an array more as a pointer than as an array.

What about
char ch = c;
?
Is this using 'c' as an array or a pointer?
Pointer.

The result is the same
whether 'c' is an array or a pointer, but I'd prefer to think of the
pointer case as behaving like an array than the array case behaving
like a pointer.


There is no array arithmetics in C++, but there is pointer arithmetics.
What happens to the array here?

Here you do not use the array.
struct S
{
char c[10];
};

void f(S &s1, S &s2)
{
s1 = s2;
}

There's no pointer behaviour in this case.

Because you do not use the name of the array.
I think it's better to list the cases where one type decays to
another than to list the exceptions.

Except if the exceptions are way less.

BTW if you do not believe me that in you example case above "c" indeed
decayed to a pointer try the following:

// Warning1 Untested code typed with flue and migrene
#include <iostream>
typedef int not_void_ever;

not_void_ever main() {
char const gree_thing[] = "Hello world!";
std::cout << "char 6: " << 6[gree_thing] << std::endl;
}

Compile it. It will. Run it. It will and it will print "char 5: w".

Why? Because 6 is an array? Nope. But because gree_thing decays into a
pointer to the first element of the character array. And then what we have
is:

something[something]

which translates to

*(something+something)

in our case

*(6+gree_thing)
 
K

Kevin Goodsell

Default said:
Kevin Goodsell wrote:





I wasn't either, so I hedged my bets :)

I'm not as strong on templates as I should be,

It seems like few people are. I know I'm not. It's a complicated topic.
I wasn't sure if you
could instantiate with array types or not. They'd be tricky, because any
resulting variables in a class would not be modifiable lvalues and all
that.

I'm not sure how it would work either, outside of things like this:

template<class T, size_t N>
void foo(T (&array)[N])
{
}

I'm not sure if this counts or not (it's what I thought of when I read
Attila's message, but maybe he was talking about something else). But I
think it points to another situation where arrays don't decay to
pointers - binding to a reference:

int a[20];
int (&r)[20] = a;

-Kevin
 
K

Kevin Goodsell

David said:
Perhaps this is a bit too strong. It's liable to cause some people to think
of an array more as a pointer than as an array.

What about
char ch = c;
?
Is this using 'c' as an array or a pointer?


A pointer, of course.
What happens to the array here?
struct S
{
char c[10];
};

void f(S &s1, S &s2)
{
s1 = s2;
}

The conversion applies when the array is referred to by name. It's often
stated something like "The name of an array becomes a pointer to the
first element of the array in most case. The exceptions are..."
I think it's better to list the cases where one type decays to another than
to list the exceptions.

But there are far more cases where it becomes a pointer - that's the
norm. I doubt I could list them all. In C there are only the 2 cases
where it doesn't. We're still discussing what additional cases are added
in C++.

-Kevin
 
D

David White

White Wolf said:
David said:
Perhaps this is a bit too strong. It's liable to cause some people to
think of an array more as a pointer than as an array.

What about
char ch = c;
?
Is this using 'c' as an array or a pointer?
Pointer.

The result is the same
whether 'c' is an array or a pointer, but I'd prefer to think of the
pointer case as behaving like an array than the array case behaving
like a pointer.


There is no array arithmetics in C++, but there is pointer arithmetics.
What happens to the array here?

Here you do not use the array.


Yes I do, implicitly.
struct S
{
char c[10];
};

void f(S &s1, S &s2)
{
s1 = s2;
}

There's no pointer behaviour in this case.

Because you do not use the name of the array.

Does it really matter? The array is being used in the code above, and not
like a pointer. The contents of s1.c are replaced.
I think it's better to list the cases where one type decays to
another than to list the exceptions.

Except if the exceptions are way less.

BTW if you do not believe me that in you example case above "c" indeed
decayed to a pointer try the following:

// Warning1 Untested code typed with flue and migrene
#include <iostream>
typedef int not_void_ever;

not_void_ever main() {
char const gree_thing[] = "Hello world!";
std::cout << "char 6: " << 6[gree_thing] << std::endl;
}

Compile it. It will. Run it. It will and it will print "char 5: w".

Why? Because 6 is an array? Nope. But because gree_thing decays into a
pointer to the first element of the character array. And then what we have
is:

something[something]

which translates to

*(something+something)

in our case

*(6+gree_thing)

So, an array, unlike a pointer, contains no address and some number of
actual characters, yet we are to think of it as an address and no
characters. And a pointer, which contains just an address and no characters,
we are to think of as an array of characters (for the purposes of array
anyway). It's not surprising that newbies have to ask lots of questions
here.

Nothing above surprises me, though I'd forgotten the quirky reversal of
array and index that I now remember seeing years ago, but for practical
purposes I'll stick to thinking of an array as an array and a pointer as a
pointer. Below is one reason why:

char c[10];
char d[10];
char *p = &c[0];
char *q = &d[0];

p = q; // okay
p = d; // okay
c = d; // error

This is another exception.

DW
 
D

David White

Kevin Goodsell said:
David White wrote:
The conversion applies when the array is referred to by name. It's often
stated something like "The name of an array becomes a pointer to the
first element of the array in most case. The exceptions are..."

I would think that people, newbies in particular, are interested in all the
differences betweeen pointers and arrays, not just those where the name is
used. I can see no good reason to single out uses of the name alone.
But there are far more cases where it becomes a pointer - that's the
norm. I doubt I could list them all. In C there are only the 2 cases
where it doesn't. We're still discussing what additional cases are added
in C++.

If you list the exceptions and you miss one, the statement "An array is
treated as a pointer except..." becomes a false statement. But if you say,
"An array decays to a pointer where a pointer is expected," you at least
aren't making a false statement if there are other cases as well. So far the
exceptions in C++ are:
sizeof, address of, template parameter, default assignment of structs and
classes, and that an array is not an l-value.

That's quite a few, and are we certain there aren't more?

DW
 
W

White Wolf

David said:
Yes I do, implicitly.

No, you are not. Using the array in this context (decaying) means using the
arrays name. It is not the array which decays, it is name.
Does it really matter?

Yes it does. It is nto the array decaying into a pointer: its name does.
So, an array, unlike a pointer, contains no address and some number of
actual characters, yet we are to think of it as an address and no
characters.

No. We are talking about array *names* and not arrays.
And a pointer, which contains just an address and no
characters, we are to think of as an array of characters (for the
purposes of array anyway). It's not surprising that newbies have
to ask lots of questions here.


Nope. Array *names* behave like pointers to the arrays first element - most
of the cases. Pointers _never_ behave like arrays.
Nothing above surprises me, though I'd forgotten the quirky reversal
of array and index that I now remember seeing years ago, but for
practical purposes I'll stick to thinking of an array as an array and
a pointer as a pointer.

No one asked you to stop think about an array as an array and a pointer as a
pointer. But please also think about the _name_ of the array as one which ,
in certain contexts, can decay into naming a pointer rvalue. Not ever as an
lvalue as you example tried to show.
 
W

White Wolf

David said:
I would think that people, newbies in particular, are interested in
all the differences betweeen pointers and arrays, not just those
where the name is used. I can see no good reason to single out uses
of the name alone.

You mean that we should not mention one very important rule of the language
just because at first sight it differs from other languages?
If you list the exceptions and you miss one, the statement "An array
is treated as a pointer except..." becomes a false statement.

It is _always_ a false statement. And array is *never* treated as a
pointer. The *name* of the array *variable* can behave as or decay into a
pointer.
But if
you say, "An array decays to a pointer where a pointer is expected,"
you at least aren't making a false statement

You are. The array never decays into anything.

T foo;

Suppose the above is an array declaration. The array is a variable. It has
an object part (the associated continuous region of storage) and a name
part, which we use to refer to that storage and a type part, which tells
what is in that storage, how big that storage is etc.

The array is the object (the storage) with its type. The word foo is the
name of the variable. We use the name of the variable to refer to the
storage. Now in some cases, foo refers to that storage as a pointer to its
first element, while in another cases it represent the whole storage with
all the elements in it.
So far the exceptions in C++ are:
sizeof, address of, template parameter,
Yes.

default assignment of structs
and classes,

No. In the default assignment of classes the _name_ of the array is not
used.
and that an array is not an l-value.
That's quite a few, and are we certain there aren't more?

The standard lists those.
 

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
474,142
Messages
2,570,819
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top