String Constant absent in C++

  • Thread starter karthikbalaguru
  • Start date
K

karthikbalaguru

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
 
G

Gianni Mariani

karthikbalaguru said:
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.
 
P

peter koch

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.

This is not correct. In both C and C++ str1 is a constant pointer to
char. An attempt to modify it causes undefined behaviour, which could
result in anything - including the behaviours mentioned above. In
practice, the behaviour depends on where the compiler decides to put
its string constants.
The correct way to initialise such a pointer is to remember the const:
eg.

char const* str1 = "Cplusplus".

char* is a special case and the only place where you can leave out the
const. It was made special in order to faciliate porting old C and C++
code.
So, str1 is not a string constant in C++.

So yes it is...
Does it mean that string constant concept is absent in C++ ?
.... and no it is not.

/Peter
 
I

Ian Collins

karthikbalaguru said:
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
 
P

Pete Becker

karthikbalaguru said:
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.
 
G

Gianni Mariani

Pete said:
On 2007-09-02 06:43:07 -0400, Gianni Mariani <[email protected]> said: ....
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 *?
 
J

Jerry Coffin

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++.
 
J

Jerry Coffin

[ ... ]
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++.
 
A

Andrew Koenig

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.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Andrew said:
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.
 
P

Pete Becker

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.
 
K

Keith Thompson

peter koch said:
This is not correct. In both C and C++ str1 is a constant pointer to
char. An attempt to modify it causes undefined behaviour, which could
result in anything - including the behaviours mentioned above. In
practice, the behaviour depends on where the compiler decides to put
its string constants.

That's not correct either. In C, a string literal is of type array of
char. Attempting to modify a string literal invokes undefined
behavior, not because it's const (it isn't), but because the C
standard explicitly says that attempting to modify a string literal
invokes undefined behavior.
The correct way to initialise such a pointer is to remember the const:
eg.

char const* str1 = "Cplusplus".
Agreed.

char* is a special case and the only place where you can leave out the
const. It was made special in order to faciliate porting old C and C++
code.


So yes it is...

Well, no, str1 is an object of type char*.

[...]
 
K

Keith Thompson

Pete Becker said:
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.
 
G

Gianni Mariani

Pete said:
On 2007-09-02 08:51:08 -0400, Gianni Mariani <[email protected]> said: ....

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.
 
P

Pete Becker

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.

Sure: since you have to make some changes, why not make a bunch more?
Have you ever had to retrofit const into an application that didn't use
it?
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.

That's always allowed.
I think we'll just have to agree to disagree.

Shrug.
 
G

Gianni Mariani

Pete said:
On 2007-09-02 15:13:46 -0400, Gianni Mariani <[email protected]> said: ....
Sure: since you have to make some changes, why not make a bunch more?
Have you ever had to retrofit const into an application that didn't use it?

Yes. It was a one time quite painless exercise, apart from having to
fix real problems which even then were pretty trivial.
 
P

Pete Becker

Yes. It was a one time quite painless exercise, apart from having to
fix real problems which even then were pretty trivial.

Then you had a very unusual experience, or a very simple application.
In any event, since you haven't cited widespread problems arising from
the conversion in questuon, it seems like this "issue" doesn't exist in
practice. The conversion is almost entirely harmless, and requiring
everyone to eliminate it in standard-conforming code would elevate form
over substance.
 
T

Tobias

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
 
K

karthikbalaguru

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*


Correct, nor is it one in C. It may point to a string literal, but it
isn't declared const.


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

Thats interesting. Thx Ian.

Further from Peter's reply. I conclude.
In both C and C++ str1 is a constant pointer to char. An attempt to
modify it causes undefined
behaviour. The correct way to initialise such a pointer is to remember
the const:
eg.

char const* str1 = "Cplusplus".

char* is a special case and the only place where you can leave out the
const. It was made special in
order to faciliate porting old C and C++ code.

Thx,
Karthik Balaguru
 
J

James Kanze

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.
 

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,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top