pointer to const string

D

Dead Loop

Hi all,
I'm a beginner and my question is:
Are there any differences between
char *p = "Hello, world!";
and
const char *p = "Hello, world!";
?
 
D

Dead Loop

// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

Thanks for any advice!
 
J

jaysome

// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

http://www.c-faq.com/ansi/strlitnotconst.html

comp.lang.c FAQ list Question 11.8b
Q: If you can't modify string literals, why aren't they defined as
being arrays of const characters?

A: One reason is that so very much code contains lines like

char *p = "Hello, world!";

which are not necessarily incorrect. These lines would suffer the
diagnostic messages, but it's really any later attempt to modify what
p points to which would be problems.

See also question 1.32.
 
S

santosh

Dead said:
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

Modifying string literals leads to undefined behaviour.
 
M

MQ

Dead said:
Hi all,
I'm a beginner and my question is:
Are there any differences between
char *p = "Hello, world!";
and
const char *p = "Hello, world!";
?

You shouldn't modify string literals, as it leads to undefined
behaviour. I believe on Windows platforms, string literals are kept in
a read-only data segment. Some systems may put them in a read/write
data segment
 
R

Richard Heathfield

Dead Loop said:
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

The C Standard says, in effect, "don't do that", but doesn't actually
prevent you from doing it. It's like a sign next to a broken bridge:
"Bridge Out - Turn Around And Go Back While There Is Still Time!". If you
want to try to cross it anyway, that's your problem, not the sign's
problem. MSVC is within its rights to prevent modification of a string
literal, and TI is within its rights to allow it. The Standard only says
that, if you try, the behaviour of the program is undefined. So any
behaviour is allowed, including allowing it (TI), disallowing it (MSVC),
and launching an Exocet missile at a passing cruiser (which is how the
Falklands War really started).
 
A

Allen

"Dead Loop дµÀ£º
"
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

Thanks for any advice!

I just write a simple c program to test this.

Code snippets as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
//p_const[0] = 'A'; // Error: assignment of read-only location
p[0] = 'A';

Both gcc(in dev-c++) and msvc6 can compile right. But both run ERROR.
This means that memory can not be written, that is, "You shouldn't
modify string literals".


besides,
when I debug it in dev-c++ and msvc6, I find that both p & p_const
point to the same address.
 
R

Richard Heathfield

Allen said:

I just write a simple c program to test this.

Code snippets as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
//p_const[0] = 'A'; // Error: assignment of read-only location
p[0] = 'A';

Both gcc(in dev-c++) and msvc6 can compile right. But both run ERROR.
This means that memory can not be written, that is, "You shouldn't
modify string literals".

The reverse, however, is not the case. Had your experiment not uncovered a
run-time error, that would not have implied that the code was correct C.

Experimentation gives empirical results, not proofs (but, as you have
discovered, it can certainly provide counter-examples).
 
S

santosh

Richard said:
Dead Loop said:
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

The C Standard says, in effect, "don't do that", but doesn't actually
prevent you from doing it. [...]
MSVC is within its rights to prevent modification of a string
literal, [...]

Can MSVC be a conforming compiler by preventing modification of string
literals?
 
R

Richard Heathfield

santosh said:
Richard said:
Dead Loop said:
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

The C Standard says, in effect, "don't do that", but doesn't actually
prevent you from doing it. [...]
MSVC is within its rights to prevent modification of a string
literal, [...]

Can MSVC be a conforming compiler by preventing modification of string
literals?

Sure. If you try to do it, the behaviour is undefined, so all bets are off.
Implementations can do what they like, and that certainly includes
preventing the modification.

Some implementations put string literals into read-only memory. That might
be "logically" read-only, in the sense that the implementation simply
enforces a "you can look but you'd better not touch" policy, or it might
even be physically read-only, in the sense that the hardware for updating
the memory is simply not present.
 
C

CBFalconer

Richard said:
Dead Loop said:
// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

The C Standard says, in effect, "don't do that", but doesn't actually
prevent you from doing it. It's like a sign next to a broken bridge:
"Bridge Out - Turn Around And Go Back While There Is Still Time!". If you
want to try to cross it anyway, that's your problem, not the sign's
problem. MSVC is within its rights to prevent modification of a string
literal, and TI is within its rights to allow it. The Standard only says
that, if you try, the behaviour of the program is undefined. So any
behaviour is allowed, including allowing it (TI), disallowing it (MSVC),
and launching an Exocet missile at a passing cruiser (which is how the
Falklands War really started).

I didn't realize that the DeathStar 9000 was available then. Was
this remarkable foresight by Maggie? Circa 1982, I believe, and
predating the C standard.
 
P

pete

CBFalconer wrote:
I didn't realize that the DeathStar 9000 was available then.

"DeathStation" !!!

It's a computer, not a satellite.

"I ran it on my DeathStation 9000 and demons flew out of my nose"
12 Aug 1998 15:51:08 -0700, (e-mail address removed) (Kaz Kylheku)
 
A

Allen

"Richard Heathfield дµÀ£º
"
Allen said:

I just write a simple c program to test this.

Code snippets as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
//p_const[0] = 'A'; // Error: assignment of read-only location
p[0] = 'A';

Both gcc(in dev-c++) and msvc6 can compile right. But both run ERROR.
This means that memory can not be written, that is, "You shouldn't
modify string literals".

The reverse, however, is not the case. Had your experiment not uncovered a
run-time error, that would not have implied that the code was correct C.

Experimentation gives empirical results, not proofs (but, as you have
discovered, it can certainly provide counter-examples).

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

I agree with you.

But,
I post that thread just want to show that Dead Loop made a mistake in
his question.
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
There is a mistake.
p_const[0] = 'A'; // this is a compile error
p[0] = 'A'; // this is run-time error
we konw that, these are different types of error. But if we say
compiler "allow" xxx , I think, it means there isn't any compile error.

p.s. English is not my mather language. Maybe I didn't say it clearly :(
 
K

Keith Thompson

Richard Heathfield said:
santosh said:
Richard said:
Dead Loop said:

// more information
If I define p & p_const in a function as follows:
char *p = "Hello, world!";
const char *p_const = "Hello, world!";
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
What about the C standard?

The C Standard says, in effect, "don't do that", but doesn't actually
prevent you from doing it. [...]
MSVC is within its rights to prevent modification of a string
literal, [...]

Can MSVC be a conforming compiler by preventing modification of string
literals?

Sure. If you try to do it, the behaviour is undefined, so all bets are off.
Implementations can do what they like, and that certainly includes
preventing the modification.

On the other hand, actually treating string literals as "const" is
potentially non-conforming. gcc, for example, does this with
"-Wwrite-strings", but that by itself doesn't make gcc non-conforming;
it merely causes it to issue some (misleading) warning messages.

For example, this program:

#include <stdio.h>
int main(void)
{
char *s = "hello, world";
puts(s);
return 0;
}

is strictly conforming (modulo any questions about the success or
failure of writing to stdout). But if string literals really were
const, then assigning the address of one to a non-const char* would be
a constraint violation. gcc with "-Wwrite-strings" warns:

c.c:4: warning: initialization discards qualifiers from pointer target type

But the program still compiles and executes, and an implementation can
issue any extraneous diagnostics it likes.

With "-Wwrite-strings -Werror", gcc rejects this program, and is
therefore non-conforming.

Assigning the address of a string literal to a non-const char* creates
the *potential* for attempting to modify the literal. A conforming
compiler is not allowed to reject the program based on that potential.
But if the program actually attempted to modify the string literal:

char *s = "hello, world";
s[0] = 'h';

that would invoke undefined behavior, and one valid consequence of
that is rejecting the program during compilation.

Enclosing the assignment in "if (0) { ... }" raises some interesting
questions, but I've already strayed enough from what the OP was
actually asking.

Hmm. I wonder if MSVC6.0 was being invoked as a C++ compiler. I
think C++ has different rules about string literals than C does.
 
K

Keith Thompson

pete said:
"DeathStation" !!!

It's a computer, not a satellite.

"I ran it on my DeathStation 9000 and demons flew out of my nose"
12 Aug 1998 15:51:08 -0700, (e-mail address removed) (Kaz Kylheku)

The DeathStation 9000 was invented in 1998. Shortly thereafter,
somebody executed a program on it that included the statement
"i = i++;"; this caused a fully operational DS9K to appear in 1982.
That machine is believed to be responsible for a number of other
unpleasant historical events (see Chicxulub), but that, of course, is
off-topic.
 
I

Ian Collins

Keith said:
On the other hand, actually treating string literals as "const" is
potentially non-conforming. gcc, for example, does this with
"-Wwrite-strings", but that by itself doesn't make gcc non-conforming;
it merely causes it to issue some (misleading) warning messages.

For example, this program:

#include <stdio.h>
int main(void)
{
char *s = "hello, world";
puts(s);
return 0;
}

is strictly conforming (modulo any questions about the success or
failure of writing to stdout). But if string literals really were
const, then assigning the address of one to a non-const char* would be
a constraint violation.
Another case where the C++ committee made the right call and the C
committee missed an opportunity.
 
K

Keith Thompson

Ian Collins said:
Another case where the C++ committee made the right call and the C
committee missed an opportunity.

But the C committee had a good reason to make the call it made.
Making string literals const would have broken every single pre-ANSI
program that passed a string literal as an argument to a function
outside the standard library. Pre-ANSI C didn't have the "const"
keyword, so it wasn't possible to declare a parameter of type "const
char*". (I exclude the standard library because it can be updated
with "const" keywords along with the rest of the implementation.)

C++, being a new language, was not as constrained by backward
compatibility.

It *might* have been worthwhile to make the change in C99, but it
still would have broken existing code and likely slowed adoption even
more.

(I think C++ is a bit lax about const-correctness in some cases, but I
don't remember the (off-topic) details.)
 
I

Ian Collins

Keith said:
But the C committee had a good reason to make the call it made.
Making string literals const would have broken every single pre-ANSI
program that passed a string literal as an argument to a function
outside the standard library. Pre-ANSI C didn't have the "const"
keyword, so it wasn't possible to declare a parameter of type "const
char*". (I exclude the standard library because it can be updated
with "const" keywords along with the rest of the implementation.)

C++, being a new language, was not as constrained by backward
compatibility.
It was to the extent that there was plenty of pre-standard code in use.
The benefits of the change where judged to outweigh the cost. I still
think C should have gone the same way. At least it would reduce the
traffic here!

Like any language change, compiler writers are free to add backwards
compatibility options.
 
D

Dead Loop

"Allen Said£º
"
I post that thread just want to show that Dead Loop made a mistake in
his question.
It seems that a TI's compiler doesn't allow
p_const[0] = 'A';
but it allows
p[0] = 'A';
And MSVC6.0 doesn't allow both of them.
There is a mistake.
p_const[0] = 'A'; // this is a compile error
p[0] = 'A'; // this is run-time error
we konw that, these are different types of error. But if we say
compiler "allow" xxx , I think, it means there isn't any compile error.

p.s. English is not my mather language. Maybe I didn't say it clearly :(

Hi Allen,
I really didn't describe it clearly. Thanks for your help! ^_^
 
D

Dead Loop

Hi all,
thanks for your help!
I understand that
1) I cannot modify the string by ^pointer p^ because it points to a
literal string.
2) I cannot modify the string by ^pointer p_const^ because first it is
(const char *) type and second it points to a literal string.
Am I right?
 

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
474,263
Messages
2,571,062
Members
48,769
Latest member
Clifft

Latest Threads

Top