Questions about "char *" and "const char*"

L

liujiaping

I'm confused about the program below:

int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}

I know there are differences between "char*" and "char[]", but I dont
know why. And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

I'm confused about the program below:

int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

}

I know there are differences between "char*" and "char[]", but I dont
know why. And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?

Nope, const char* is const char* and char* is char*. What happens here
is that str7 is a pointer to some location in memory which contains
the string "abc". Now, what is this piece of memory that it's pointing
to? It's a string constant, so even though str7 is not declared to
point to a string constant it does so anyway, just like you can have a
const char* point to a non-constant string.
 
Y

yoviesmanda

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

I ever have found this problem. In the source above,
if you want to get or set the value of str7, you can add
"*" before str7. So, you can write " *str7[0] = 'd' ".

why we must add "*", same with Erik say that str7 is pointer.
 
I

Ian Collins

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}

I ever have found this problem. In the source above,

Well you should, attempting to write to a string literal is undefined
behaviour.
if you want to get or set the value of str7, you can add
"*" before str7. So, you can write " *str7[0] = 'd' ".
Nonsense, *str7[0] is an attempt to dereference a char!
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}

I ever have found this problem. In the source above,
if you want to get or set the value of str7, you can add
"*" before str7. So, you can write " *str7[0] = 'd' ".

why we must add "*", same with Erik say that str7 is pointer.

Nope, *str7[0] would require str7 to be of type char*[] (array of
pointers to char), since you first index into an array and then try to
dereference what you found there.

The reason you can't do str7[0] = 'd' is that the memory location you
are trying to modify is read only.
 
L

liujiaping

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

I know there are differences between "char*" and "char[]", but I dont
know why. And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?

Nope, const char* is const char* and char* is char*. What happens here
is that str7 is a pointer to some location in memory which contains
the string "abc". Now, what is this piece of memory that it's pointing
to? It's a string constant, so even though str7 is not declared to
point to a string constant it does so anyway, just like you can have a
const char* point to a non-constant string.

Thanks for your help. So str7 is not constant, but it points to a
constant
string "abc". If both a const char* and a char* point to a non-
constant
string, if the char* changes the string, then the const char* points
to the
string changed by the char* too, am I right? Another question, str1
points to
"abc" too, why can str1 change the string by the statement "str1[0] =
'd';"
but str7 can't? I heard that the constant string "abc" which str7
points to is
in the bss area, and the string str1 point to is in the static area.
What's
the difference between them?
 
I

Ian Collins

liujiaping said:
I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}
I know there are differences between "char*" and "char[]", but I dont
know why. And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?

Nope, const char* is const char* and char* is char*. What happens here
is that str7 is a pointer to some location in memory which contains
the string "abc". Now, what is this piece of memory that it's pointing
to? It's a string constant, so even though str7 is not declared to
point to a string constant it does so anyway, just like you can have a
const char* point to a non-constant string.

Thanks for your help. So str7 is not constant, but it points to a
constant
string "abc".

It points to a string literal "abc".
If both a const char* and a char* point to a non-constant
string, if the char* changes the string, then the const char* points
to the
string changed by the char* too, am I right?

Yes, they both point to the same mutable object.
Another question, str1 points to
"abc" too, why can str1 change the string by the statement "str1[0] =
'd';"

str1 is a (mutable) automatic array. It is not a constant.
but str7 can't? I heard that the constant string "abc" which str7
points to is
in the bss area, and the string str1 point to is in the static area.
What's
the difference between them?
There isn't a bss area in standard C++, it's an implementation detail.
str1 is an automatic variable, str7 is a pointer to a string literal.
 
J

James Kanze

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
//str7[0] = 'd'; // error too
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}
I know there are differences between "char*" and "char[]", but I dont
know why.

What do you mean, you don't know why? Why on earth should there
not be differences. They're radically different, unrelated
types. char[] is an array, char* a pointer.
And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?

No. It means that you've stumbled on a loop-hole in the C++
type system. Historically, there wasn't const, and people wrote
`char* p = "abc"', knowing that *p couldn't be modified. When
const was introduced, it was originally felt (in the C
community) that making "abc" const would break too much code, so
they created the idea of a non-const object that you're not
allowed to modify. C++ (where const is a lot more important
than in C) handled the problem slightly differently: "abc" is a
char const[4], and converts implicitly to char const*, but there
is a special, deprecated conversion to char* if (and only if)
the char const* is the result of the array to pointer conversion
on a string literal.

IMHO, it's best to ignore this, and treat `char* s = "abc"' as
an error. Good compilers will warn. (Curiously enough, g++
doesn't, alghough it's usually pretty good with warnings.)
 
G

Greg Comeau

I'm confused about the program below:
int
main(int argc, char* argv[])
{
char str1[] =3D "abc";
char str2[] =3D "abc";
const char str3[] =3D "abc";
const char str4[] =3D "abc";
const char* str5 =3D "abc";
const char* str6 =3D "abc";
//str6[0] =3D 'd'; // of coz error
char* str7 =3D "abc";
//str7[0] =3D 'd'; // error too
cout << boolalpha << (str1 =3D=3D str2) << endl; // false
cout << boolalpha << (str3 =3D=3D str4) << endl; // false
cout << boolalpha << (str5 =3D=3D str6) << endl; // true
cout << boolalpha << (str6 =3D=3D str7) << endl; // true
return 0;
}

I ever have found this problem. In the source above,
if you want to get or set the value of str7, you can add
"*" before str7.

But only if it points to a modifiable entity.

Of course, if it is modifiable, it need not only be the first
char that can be modified.
So, you can write " *str7[0] =3D 'd' ".

No, that's a double dereference (& and []).
So you meant either *str7 = 'd'; or str7[0] = 'd';

However, that runs into another problem: pointing to
a string literal, as the str7 initializer establishes,
means that you should only read from and not write through
that pointer. There reason why is because C or C++ may
put the string in a read only area (and string literals are
literally const in C++ BTW) and also might do something like
merge similar string literals.

Note that this is not the case with say str1[] because post
initialization, str1 is 'a' 'b' 'c' '\0' which is different
than str7 which points to an unnamed array. If one did
str7 = str1; there would not be the string literal problem
mentioned above.

Anyway, so str1 and str2 are distince addresses, hence
the first output will be false, ditto for str3 vs str4.
This compares addresses not content at the addresses.

However, str5 vs str6, and str6 vs str7, may be either
true or false, we don't know which until we run the program
with a specific compiler in a specific mode, and even at that,
it could theoratically be ramdom results, because "abc" here
and "abc" there may or may notbe the same unnamed array.
why we must add "*", same with Erik say that str7 is pointer.

???
 
U

uglystone

int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
str7[0] = 'd'; //strange????????
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

}
if str7[0] is uncommented,g++ compiler works well.
but while running the output file,display segement fault!
I feel very strange!
In C++, const char* shouldn't point to a non-constant string.why don't
g++ compiler complain?
 
V

Victor Bazarov

uglystone said:
int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
str7[0] = 'd'; //strange????????

"abc" is a string literal. Its type is 'const char[4]'. C++ (for
compatibility reasons) allows to initialise a pointer to non-const
char ('str7' in your case) with the address of the first character
of the array of const char. Attempting to change it has undefined
behaviour. In your case you get a crash.
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

}
if str7[0] is uncommented,g++ compiler works well.
but while running the output file,display segement fault!
I feel very strange!

As you should.
In C++, const char* shouldn't point to a non-constant string.

I think you got it the other way around. A 'char*' shouldn't point
to a constant string.
why don't
g++ compiler complain?

It is explicitly allowed.

V
 
J

James Kanze

int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
str7[0] = 'd'; //strange????????
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;
}
if str7[0] is uncommented,g++ compiler works well.
but while running the output file,display segement fault!
I feel very strange!
In C++, const char* shouldn't point to a non-constant string.why don't
g++ compiler complain?

History. The type of a string literal is char const[], not
char[], and as has been pointed out, attempting to modify it is
undefined behavior. The original C didn't have const, however,
and programmers got into the habit of writing `char *p =
"abc";', even though they knew that they shouldn't modify
through *p. (For many years, in C, there was no way of
specifying that you couldn't modify the variable through a given
pointer.) The result is that when const was introduced, string
literals were declared to have type char[], but trying to modify
them was stated to be undefined behavior. Later, C++ changed
the type to char const[], but introduced a special, hacky
conversion which is valid only for string literals. Just to
avoid breaking existing code.

Note that in the earliest versions of C, even modifying through
*p was legal. It was considered very bad practice, however,
since that meant that the next time you executed:
p = "abc" ;
you actually set p to point to "xyz". Very confusing for the
maintenance programmer. Standard C and C++ decided not to
support this usage, but some compilers still do; even g++ will
if you give it the right option.

Curiously enough, of the two compilers I use daily, Sun CC warns
if you assign a string literal to a char*, but supports writable
string literals by default, and g++ doesn't warn, but string
literals are not writable by default. Sometimes one wonders if
the left hand knows what the right hand is doing.

(All of that just to say that you're perfectly entitled to feel
very strange.)
 
J

James Kanze

[...]
There isn't a bss area in standard C++, it's an implementation detail.

But there was, in the original implementations of C:). On the
other hand, string literals were never put in the bss segment;
that was reserved for variables with default initialization and
for dynamically allocated memory. In the very oldest
implementations of C, string literals were in data, however, and
could be written. (In the very, very oldest implementations of
C, there was no write protected text segment, either, and an
uninitialized pointer could change your code. Which makes me
wonder why they called it the *good* old days.)

I'll admit that it is rather surprising to hear a beginner talk
about such things. I don't think I've heard the bss segment
mentioned in the last fifteen years.
 
I

Ian Collins

James said:
But there was, in the original implementations of C:). On the
other hand, string literals were never put in the bss segment;
that was reserved for variables with default initialization and
for dynamically allocated memory. In the very oldest
implementations of C, string literals were in data, however, and
could be written.

Some compilers still do. For "compatibility" reasons, Sun cc still
defaults to string literals in the data segment.

Is there any way you can fix this, it is realy annoying!
 
D

Default User

liujiaping wrote:

I know there are differences between "char*" and "char[]", but I dont
know why. And since *str7 cannot be changed, does this mean that
"char*" is equvalent to "const char*"?



Pointers are a somewhat primitive mechanism. You may want to review the
C FAQ, which while for another language goes over this stuff pretty
well.

<http://c-faq.com/decl/strlitinit.html>

I'd recommend looking over all the questions in the Pointers and Arrays
section:

<http://c-faq.com/aryptr/index.html>





Brian
 
D

Default User

James Kanze wrote:

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


A small (but important) technical note. The proper separator for .sigs
is "-- " (dash dash space). Yours is missing the space. Correct
separators allow newsreaders to auto-trim signatures.





Brian
 
G

Greg Comeau

int
main(int argc, char* argv[])
{
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
//str6[0] = 'd'; // of coz error
char* str7 = "abc";
str7[0] = 'd'; //strange????????
cout << boolalpha << (str1 == str2) << endl; // false
cout << boolalpha << (str3 == str4) << endl; // false
cout << boolalpha << (str5 == str6) << endl; // true
cout << boolalpha << (str6 == str7) << endl; // true
return 0;

}
if str7[0] is uncommented,g++ compiler works well.
but while running the output file,display segement fault!
I feel very strange!
In C++, const char* shouldn't point to a non-constant string.why don't
g++ compiler complain?

These may help:
http://www.comeaucomputing.com/techtalk/#stringliteral

http://www.comeaucomputing.com/techtalk/#ptrvsarray
 
J

James Kanze

A small (but important) technical note. The proper separator for .sigs
is "-- " (dash dash space). Yours is missing the space. Correct
separators allow newsreaders to auto-trim signatures.

Thanks. I'm aware of this, but I usually insert the .sig
manually, and it's easy to forget. (The person who specified
this should be hung, drawn and quartered. You never want
trailing whitespace to be significant.)

I'll see what I can do about automating this, so the error won't
occur.

--
 
D

Default User

James said:
Thanks. I'm aware of this, but I usually insert the .sig
manually, and it's easy to forget.

Oh, you're using Google Groups. Yeah, that makes things tougher. I
think they may actually delete space as unneeded even if its present.
(The person who specified
this should be hung, drawn and quartered. You never want
trailing whitespace to be significant.)
Perhaps.

I'll see what I can do about automating this, so the error won't
occur.

--

No, it didn't, but as I said above you may be out of luck.




Brian
 
J

James Kanze

Oh, you're using Google Groups. Yeah, that makes things tougher. I
think they may actually delete space as unneeded even if its present.

I don't think so, since it is usually there.

The real problem with Google Groups, of course, is that you're
reading the group in a web interface, and responding in a Post
box of your browser. Which means copying the article into a
decent editor, editing, and then pasting back. And the decent
editor generally doesn't know that it is dealing with an
article, and so doesn't know to append the signature; I have to
do it manually.

I've recently started using "It's All Text" with Firefox, so the
decent editor (gvim) is now invoked automatically, with the
text, and (in my case at least) throug a shell script. So it's
only a matter of time before I get the script set up to let vim
know that it's responding to a posting, so that it can append
the .sig automatically.

--
 

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