By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,793 Members | 1,194 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,793 IT Pros & Developers. It's quick & easy.

String Constant absent in C++

P: n/a
Hi,
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.

So, str1 is not a string constant in C++.
Does it mean that string constant concept is absent in C++ ?

Thx in advans,
Karthik Balaguru

Sep 2 '07 #1
Share this Question
Share on Google+
17 Replies


P: n/a
karthikbalaguru wrote:
Hi,
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.

So, str1 is not a string constant in C++.
Does it mean that string constant concept is absent in C++ ?
This is one of those really bad decisions by the C++ committee.

String literals are of type const char [], however, for reasons of
wisdom beyond my grasp, the standard allows sting literals (and only
string literals) to be assigned to a "char * ptr" by implicitly const
casting. More than likely, trying to modify the string literal will
cause your program to segv. Go figure.
Sep 2 '07 #2

P: n/a
karthikbalaguru wrote:
Hi,
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.
No it won't, because str1 isn't a const.

Some C++ compilers will warn that a string literal is being assigned to
a char*
So, str1 is not a string constant in C++.
Correct, nor is it one in C. It may point to a string literal, but it
isn't declared const.
Does it mean that string constant concept is absent in C++ ?
Of course not.

cat x.c

int main() {
const char *str1 = "Cplusplus";
*str1 = 'M';
}

gcc -Wall -ansi -pedantic x.c
/tmp/x.c:3: error: assignment of read-only location

g++ -Wall -ansi -pedantic x.c
/tmp/x.c:3: error: assignment of read-only location

--
Ian Collins.
Sep 2 '07 #3

P: n/a
On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi*******@mariani.wssaid:
karthikbalaguru wrote:
>Hi,
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.

So, str1 is not a string constant in C++.
Does it mean that string constant concept is absent in C++ ?

This is one of those really bad decisions by the C++ committee.

String literals are of type const char [], however, for reasons of
wisdom beyond my grasp, the standard allows sting literals (and only
string literals) to be assigned to a "char * ptr" by implicitly const
casting. More than likely, trying to modify the string literal will
cause your program to segv. Go figure.
The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is
deprecated, so portable code should not rely on it.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Sep 2 '07 #4

P: n/a
Pete Becker wrote:
On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi*******@mariani.wssaid:
....
The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is deprecated,
so portable code should not rely on it.
Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?
Sep 2 '07 #5

P: n/a
In article <11**********************@y42g2000hsy.googlegroups .com>,
ka***************@gmail.com says...
Hi,
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.
There's really no difference between the languages in this respect. In
either case, attempting to write to the string constant produces
undefined behavior. That means anything can happen in either case. Any
difference you see is an artifact of the compiler(s) you're using, not
anything mandated by the definitions of the languages -- in fact, in
both cases, the language definitions specifically do NOT mandate
anything.
So, str1 is not a string constant in C++.
Does it mean that string constant concept is absent in C++ ?
No. Your code has undefined behavior, so it means essentialy nothing
about either C or C++.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 2 '07 #6

P: n/a
In article <46dab1c0$0$28516$5a62ac22@per-qv1-newsreader-
01.iinet.net.au>, gi*******@mariani.ws says...

[ ... ]
Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?
I can't speak for Pete, but _I_ think the decision was completely
reasonable. C++ has always been designed with the explicit goal of
remaining compatible with most C code, even when it forced a comprimise
in the language in terms of safety, elegance, etc.

You can find quite a few languages that are more or less contemperaneous
with C++ that are (at least arguably) safer and more elegant -- but none
of them has anywhere close to the acceptance and user base of C++. The
ability to assign a string literal to a non-const char * has been
deprecated so at some point in the future it may disappear -- but if it
had been eliminated early on, it would have also eliminated the ability
to compile most C code as C++, and in the process would probably have
nearly killed C++.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 2 '07 #7

P: n/a
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
This is one of those really bad decisions by the C++ committee.
String literals are of type const char [], however, for reasons of wisdom
beyond my grasp, the standard allows sting literals (and only string
literals) to be assigned to a "char * ptr" by implicitly const casting.
C++ does that because C allows it too: In C, you can convert const char * to
char * without a cast.
Sep 2 '07 #8

P: n/a
Andrew Koenig wrote:
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>This is one of those really bad decisions by the C++ committee.
>String literals are of type const char [], however, for reasons of wisdom
beyond my grasp, the standard allows sting literals (and only string
literals) to be assigned to a "char * ptr" by implicitly const casting.

C++ does that because C allows it too: In C, you can convert const char *
to char * without a cast.
In C, you cannot convert a const char * to char * without a cast. In C, you
can assign a string literal to a char * without a cast, because string
literals have type array of char.
Sep 2 '07 #9

P: n/a
On 2007-09-02 08:51:08 -0400, Gianni Mariani <gi*******@mariani.wssaid:
Pete Becker wrote:
>On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi*******@mariani.wssaid:
...
>The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is
deprecated, so portable code should not rely on it.

Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?
No. There is quite a bit of existing code that does this, and having to
retrofit const modifiers, even for the vast majority of cases where the
code doesn't modify the pointee, would be a pointless exercise. If you
don't want to use the conversion, don't use it. If you want to enforce
not using it in your code, get a lint tool or turn on a compiler
warning.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Sep 2 '07 #10

P: n/a
Pete Becker <pe**@versatilecoding.comwrites:
[...]
The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is
There's a little more to the historical background than that. Early C
didn't have the 'const' keyword, so if you wanted to pass a string
literal to a function, that function had to take a 'char*' argument:

func(str)
char *str;
{
/* code that doesn't modify the string */
}

...

func("Hello, world");

If ANSI C had made string literals const, such code (which was
perfectly valid when it was written) would have been broken, and the
transition from pre-ANSI to ANSI would have been more difficult.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 2 '07 #11

P: n/a
Pete Becker wrote:
On 2007-09-02 08:51:08 -0400, Gianni Mariani <gi*******@mariani.wssaid:
....
>Knowing what you know today, would the reason you gave here be a
worthy reason to make the same decision again or if you could go back
in time, would you vote to not allow string literals to be assign to a
char *?

No.
?
... There is quite a bit of existing code that does this, and having to
retrofit const modifiers, even for the vast majority of cases where the
code doesn't modify the pointee, would be a pointless exercise. If you
don't want to use the conversion, don't use it. If you want to enforce
not using it in your code, get a lint tool or turn on a compiler warning.
There are plenty of other reasons for code to have been modified so I
don't see how the pre-existing code argument supports your position.
Also, instead of mandating this rule to be standard, you could have left
it up to the compiler supplier to provide a "compatability" flag as many
do for some reason or another for other issues.

I think we'll just have to agree to disagree.
Sep 2 '07 #12

P: n/a
Hello,
I have to use Visual Studio 2005 at work:-(. Think, M$VC8 is the
associated compiler.
For me auto_ptr of M$ was broken. Some static cast instead of the
right dynamic one.
Makes polymorphic use impossible. Maybe, this is fixed in your version
of M$VC.
Best regards,
Tobias

Sep 3 '07 #13

P: n/a
On Sep 2, 2:51 pm, Gianni Mariani <gi3nos...@mariani.wswrote:
Pete Becker wrote:
On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi3nos...@mariani.wssaid:
...
The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is deprecated,
so portable code should not rely on it.
Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?
The decision was the only possible one. Anything else would
have broken too much code. It would have been absolutely
unacceptable to have made something like:
char* p = "abc" ;
to have been illegal. The only choice was in the mechansim
which is used to allow it. The C committee simply made the type
of "abc" char[4], and said that despite a non-const type, it was
undefined behavior to attempt to modify it. The C++ committee
went a step further, and said that "abc" had type char const[4],
but introduced a very special conversion to allow the above to
work.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
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
Sep 4 '07 #14

P: n/a
On Sep 2, 12:54 pm, Ian Collins <ian-n...@hotmail.comwrote:
karthikbalaguru wrote:
String constant being modifiable in C++ but, not modifiable in C.
that is,
In C++, the following example output will be "Mplusplus"
char *str1 = "Cplusplus";
*str1 = 'M';
In C, the above example will produce an error as we are trying to
modify a constant.
No it won't, because str1 isn't a const.
It might, or it might not. The expression "*str1 = 'M'"
attempts to modify a character in a string literal. In both C
and C++, this is undefined behavior (albeit for slightly
different reasons). Historically:

1. In K&R C, there was no const. In addition, K&R guaranteed
that 1) all string literals occupied distinct storage, and
2) that they could be modified. This last ability was
considered a defect by many, so...

2. The C standards committee declared that it was undefined
behavior to attempt such a modification (an implementation
could put the literal in write-only memory), and that it was
unspecified whether two identical string literals occupied
distinct memory or not.

The C standards committee also adopted the const keyword
from C++, but decided not to apply it to the type (char[])
of a string literal.

3. In C++, const plays a much larger role than in C. (E.g. it
is involved in function overload resolution.) For this
reason, the C++ committee decided that the type of a string
literal must be char const[], and not simply char[]. Still,
it was quite obvious that they couldn't responsibly break
things like ``char* p = "abc" ;'', so they introduced a
special conversion, which only applies in specific cases
(and which could easily cause a compiler warning when used).

For historical reasons, most C++ compilers still have an option
to treat string literals as they were treated in K&R C: as
writable objects, with guaranteed separate data for each
literal. And even today, this is the default for some
compilers (Sun CC, for example).
Some C++ compilers will warn that a string literal is being assigned to
a char*
I think that the committee really wanted to encourage such
warnings.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
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

Sep 4 '07 #15

P: n/a
James Kanze wrote:
>
It might, or it might not. The expression "*str1 = 'M'"
attempts to modify a character in a string literal. In both C
and C++, this is undefined behavior (albeit for slightly
different reasons). Historically:
2. The C standards committee declared that it was undefined
behavior to attempt such a modification (an implementation
could put the literal in write-only memory),
Now *THAT* would be an interesting decision by the implementor. :-)
I know you meant to say "read-only memory".
Sep 4 '07 #16

P: n/a
James Kanze wrote:
On Sep 2, 2:51 pm, Gianni Mariani <gi3nos...@mariani.wswrote:
>Pete Becker wrote:
>>On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi3nos...@mariani.wssaid:
...
>>The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is deprecated,
so portable code should not rely on it.
>Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?

The decision was the only possible one. Anything else would
have broken too much code. It would have been absolutely
unacceptable to have made something like:
char* p = "abc" ;
to have been illegal. The only choice was in the mechansim
which is used to allow it. The C committee simply made the type
of "abc" char[4], and said that despite a non-const type, it was
undefined behavior to attempt to modify it. The C++ committee
went a step further, and said that "abc" had type char const[4],
but introduced a very special conversion to allow the above to
work.
I don't mean to sound like a troll but I honestly am not convinced.

What I would like to see normally happen in a case like this one is to
bite the bullet but allow the compiler supplier to provide a backwards
computability flag that allowed something like this rather than mandate
it in the standard. Instead now we have newbies completely surprised
where I mean "badly" surprised.

I have often needed to "clean up" a large codebase. For somthing like
this, I imagine that it can be made fairly mechanical. I've warmed up
the macro processor on my editor or written a little lex script a couple
of times to modify a few hundred files at a time and was quite surprised
that it worked first time which is usually the case when it's a
mechanical process.

Anyhow, I think this is one of those cases where the cure is far worse
than the problem.
Sep 6 '07 #17

P: n/a
On Sep 6, 2:20 pm, Gianni Mariani <gi3nos...@mariani.wswrote:
James Kanze wrote:
On Sep 2, 2:51 pm, Gianni Mariani <gi3nos...@mariani.wswrote:
Pete Becker wrote:
On 2007-09-02 06:43:07 -0400, Gianni Mariani <gi3nos...@mariani.wssaid:
...
The reason is that historically, C-style strings were not always
constant, and there was code that relied on this. The rule in C++ is
that the type of a string literal is array-of-const-char. The literal
can be converted into a pointer-to-char, but that you write to it at
your peril. That preserves the status quo. The conversion is deprecated,
so portable code should not rely on it.
Knowing what you know today, would the reason you gave here be a worthy
reason to make the same decision again or if you could go back in time,
would you vote to not allow string literals to be assign to a char *?
The decision was the only possible one. Anything else would
have broken too much code. It would have been absolutely
unacceptable to have made something like:
char* p = "abc" ;
to have been illegal. The only choice was in the mechansim
which is used to allow it. The C committee simply made the type
of "abc" char[4], and said that despite a non-const type, it was
undefined behavior to attempt to modify it. The C++ committee
went a step further, and said that "abc" had type char const[4],
but introduced a very special conversion to allow the above to
work.
I don't mean to sound like a troll but I honestly am not convinced.
The standard is a contract of sorts. The first version of a
standard should treat any existing de facto standards as a
previous version. Changes which break existing code violate the
contract.

Obviously, it's not an absolute. You have to weigh the
advantages versus the amount of existing code which will be
broken. In this case, at the time the standard was being
written, it was pretty clear that not allowing ``char* p =
"xyz";'' would break a lot of code---perhaps most of the
existing code at the time. The "advantage" is that a few, rare
errors would be caugt be the compiler. In this case, the
cost-benefits analysis weighs (or weighed---the decision must be
considered in its historical context) so extremely heavily to
one side that no one even seriously suggested breaking the code.
What I would like to see normally happen in a case like this one is to
bite the bullet but allow the compiler supplier to provide a backwards
computability flag that allowed something like this rather than mandate
it in the standard. Instead now we have newbies completely surprised
where I mean "badly" surprised.
I fail to see where newbies would be surprised. They should be
taught to write ``char const* p = "xyz";'', and of course, that
works. (They should also be taught that in general, that the
fact that the compiler doesn't complain doesn't mean that the
code is correct.)
I have often needed to "clean up" a large codebase.
The problem isn't only having to "clean up" your own codebase.
The problem is also interfacing with legacy code. But of
course, most organizations don't like having to make changes in
working code, either. For good reasons.
For somthing like this, I imagine that it can be made fairly
mechanical.
I rather doubt it.
I've warmed up
the macro processor on my editor or written a little lex script a couple
of times to modify a few hundred files at a time and was quite surprised
that it worked first time which is usually the case when it's a
mechanical process.
In this case, of course, you'd have to parse enough C++ to
recognize the declarations, then analyse the initialization to
see if it is a string literal (which often will be a #define, so
you'd have to preprocess as well).
Anyhow, I think this is one of those cases where the cure is far worse
than the problem.
I don't think you understand the problem. Or rather, the
problems. The current situation isn't very elegant, but it
doesn't really cause any serious problems in production (and the
intent of the committee was that compilers would *warn* when
this special conversion was used---that's one of the reasons why
the C solution wasn't adopted). And the impact of a change
would be enormous, even today. (Note that "const-correctness"
is not considered particularly important in the C community, and
many C interfaces, even today, will use "char*" even if the
function doesn't change anything. And many C++ programs will
use such interfaces.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
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

Sep 7 '07 #18

This discussion thread is closed

Replies have been disabled for this discussion.