assigning const char* to char*

P

Peithon

Hi,

This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs to
do some ptr arithmetic,
like incrementing the ptrs to compare the strings.
But I'm getting warning C4090 complaining about the assignment.
I thought I was doing the standard thing for ptr arithmetic. What am I
doing wrong?
How do I get rid of the warning?
 
R

Richard Heathfield

Peithon said:
Hi,

This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)

Although it has nothing to do with your question, I should perhaps point
out that the name strspcmp is reserved. str_spcmp is not, however.
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs to
do some ptr arithmetic,
like incrementing the ptrs to compare the strings.

You don't need to do that, and in fact it's a bad idea. The const char *
syntax doesn't mean "this pointer can't change". It means "you can't
write through this pointer". ++s1 is fine. *s1 = '\0', however, is not.
And since you don't want to do that anyway, I suggest that you use
const char * - in which case pS1 and pS2 become redundant; you might as
well use s1 and s2 directly. (Remember that C is pass-by-value, so ++s1
only changes your local copy of the pointer, not the value of the
pointer passed by the caller.)

<snip>
 
R

Richard

Peithon said:
Hi,

This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs to
do some ptr arithmetic,
like incrementing the ptrs to compare the strings.
But I'm getting warning C4090 complaining about the assignment.
I thought I was doing the standard thing for ptr arithmetic. What am I
doing wrong?
How do I get rid of the warning?

For a start you post the warning you are getting :-;
 
B

Ben Bacarisse

Peithon said:
Hi,

This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)

You are invading the implementation's name space.
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs

The pointers are not const. They point to const char. Subtle but
important distinction.
to do some ptr arithmetic,

Odd. You can do arithmetic on const char * as well and you would not
get the warnings.
like incrementing the ptrs to compare the strings.
But I'm getting warning C4090 complaining about the assignment.

As you must. It requires a diagnostic.
I thought I was doing the standard thing for ptr arithmetic. What am I
doing wrong?
How do I get rid of the warning?

Just to the pointer arithmetic on the const char *s1 and s2.
 
P

Peithon

You are invading the implementation's name space.



The pointers are not const. They point to const char. Subtle but
important distinction.


Odd. You can do arithmetic on const char * as well and you would not
get the warnings.


As you must. It requires a diagnostic.


Just to the pointer arithmetic on the const char *s1 and s2.

Thanks, I didn't see the distinction between const char * and char *
const.
Much appreciated.
 
J

Johan Bengtsson

Peithon said:
Hi,

This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs to
do some ptr arithmetic,
like incrementing the ptrs to compare the strings.
But I'm getting warning C4090 complaining about the assignment.
I thought I was doing the standard thing for ptr arithmetic. What am I
doing wrong?
How do I get rid of the warning?

typing

const char *a;

means you have a pointer to a char and are not allowed to modify what it
points to (but you are allowed to modify the pointer).
that means

char b;

a="hello";
a++;
b=*a;

is valid code, but not:
a=&b;
*a=' '; /* this line is not valid */

since this is valid:

char *c;
c=&b;
*c=' ';

but modifying something pointed to by a const pointer is not is this
also not valid:

a=&b;
c=a; /* gives the warning you mentioned */
*c=' '; /* this statement is still valid */
 
K

Keith Thompson

Peithon said:
This is a very simple question but I couldn't find it in your FAQ.

I'm using VC++ and compiling a C program, using the /TC flag.

I've got a function for comparing two strings

int strspcmp(const char * s1, const char * s2)
{

char* pS1 = s1;
char* pS2 = s2;
...
...

}

As you can see, I assign the two const ptrs to some non-const ptrs to
do some ptr arithmetic,
like incrementing the ptrs to compare the strings.
But I'm getting warning C4090 complaining about the assignment.
I thought I was doing the standard thing for ptr arithmetic. What am I
doing wrong?
How do I get rid of the warning?

This has already been ably answered, but perhaps a simpler example
might make the point clearer. I think your point of confusion is that
"const char*" means "pointer to const char", not "const pointer to
char", but I'll explore other issues as well.

int main(void)
{
const char *ptr = "hello";
char *copy_of_ptr = ptr;
*ptr = 'H';
return 0;
}

The declaration "const char *ptr" doesn't make ptr const; it makes
what it points to const. Here I've initialized ptr to point to a
string literal, i.e., to an array of 6 characters 'h', 'e', 'l', 'l',
'o', '\0'. This array could be stored in read-only memory; attempting
to modify it could cause the program crash (it's undefined behavior).

The declaration of copy_of_ptr doesn't use the "const" keyword, which
means I'm allowed to modify either the pointer object itself *or* what
it points to. By "allowed to", I mean that the compiler won't
complain if I try to do it; it will go ahead and generate code to do
what I asked. It's up to me to make sure that I actually *can* modify
whatever I'm trying to modify. If I lie to the compiler, it may or
may not complain.

But in this case, I *tried* to lie to the compiler and it caught me at
it. I attempted to initialize a char* to the value of ptr. If I
could do this, it would allow me to (attempt to) modify whatever
copy_of_ptr points to. And that's exactly why the language forbids
assigning the value of ptr to copy_of_ptr (it's a constraint
violation, requiring a diagnostic). My error is caught during
compilation, when I attempt to copy the pointer, which is much better
than not catching it until run time, when I actually try to modify the
string.

If the language, and therefore the compiler, allowed me to copy the
value of ptr to copy_of_ptr, then it would also allow me to attempt to
modify the string that it points to (remember that it might be in
read-only memory), all without telling me that I've done something
dangerous. Fortunately, the rules of the language are such that I
can't get away with this particular error quite so easily. (It is
overly lax about string literals, but that's another story.)

If you want a pointer to const char, declare it as:

const char *ptr;

If you want a const pointer to char (you can't modify the pointer, but
you can modify what it points to):

char *const ptr;

And if you want both the pointer *and* what it points to be read-only:

const char *const p;

The placement of the "const" keyword is tricky. If you can find a
program called "cdecl", it can help you with this kind of thing; I
used it to confirm these declarations.

% cdecl
Type `help' or `?' for help
cdecl> declare p as const pointer to char
char * const p
cdecl> declare p as const pointer to const char
const char * const p
cdecl> explain const char *p
declare p as pointer to const char
cdecl>

One thing to watch out for: cdecl treats "ptr" as a synonym for
"pointer", so if you tell it "declare ptr as pointer to const char" it
will report a syntax error.
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top