char * vs. const char *

J

Joachim Schmitz

Hi folks

Is it legal for a C compiler that claims to be conforming to the standard
(c89) to issue an error on the following:

char *foo(const char *s)
{
const char *s;
for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++)

if (*s == c)

return s;

....

}

I get 2 errors when compiling this:

error(212): return value type does not match the function type

error(611): a value of type "const char *" cannot be assigned to an entity
of type "char *"

I'd understand a warning, but an error?

Bye, Jojo
 
J

Jeremy Yallop

Joachim said:
Is it legal for a C compiler that claims to be conforming to the standard
(c89) to issue an error on the following:

Yes. In fact, a conforming compiler is /obliged/ to diagnose this
code.
char *foo(const char *s)
{
const char *s; [...]

I'd understand a warning, but an error?

There's no distinction between warnings and errors in C89: the
standard requires that "diagnostics" are issued for certain
violations. After such a diagnostic has been issued the compiler is
under no obligation to continue translation.

Jeremy.
 
J

Joachim Schmitz

Hi Jeremy

Jeremy Yallop said:
Joachim said:
Is it legal for a C compiler that claims to be conforming to the standard
(c89) to issue an error on the following:

Yes. In fact, a conforming compiler is /obliged/ to diagnose this
code.
char *foo(const char *s)
{
const char *s; [...]

I'd understand a warning, but an error?

There's no distinction between warnings and errors in C89: the
standard requires that "diagnostics" are issued for certain
violations. After such a diagnostic has been issued the compiler is
under no obligation to continue translation.
Thanks,

Well, unfortunaly the Samba code is full of such things and I have to insert
(char *) all over the place to get it compiled...
If a compiler is allowd to choke on this, it'd be a bug in Samba and I'll
report it as such. Otherwise I'd report it as a bug against our c89...
Bye, Jojo
 
A

Alex Monjushko

Joachim Schmitz said:
Is it legal for a C compiler that claims to be conforming to the standard
(c89) to issue an error on the following:
char *foo(const char *s)
{
const char *s;
for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++)
if (*s == c)
return s;


I get 2 errors when compiling this:
error(212): return value type does not match the function type
error(611): a value of type "const char *" cannot be assigned to an entity
of type "char *"
I'd understand a warning, but an error?

The compiler is obligated to emit a diagnostic in this case. Whether
it is a warning or an error is not germane as far as the standard is
concerned.
 
A

Arthur J. O'Dwyer

Is it legal for a C compiler that claims to be conforming to the standard
(c89) to issue an error on the following:

char *foo(const char *s)
{
const char *s;

Most compilers I know will issue a (non-required) diagnostic for
this definition, as it shadows a parameter with the same name.
for (s = src;

Here you will get a (required) diagnostic: 'src' has never been
declared. I don't think any compiler will continue compilation
after this line.
*s && !(((unsigned char)s[0]) & 0x80); s++)

As far as I can tell, this is just a fancier and slightly less
portable way of writing

for (s = src; (*s != 0) && ((unsigned)*s < 0x80u); ++s)

Note that even that cast to 'unsigned' could be dropped, but then
some compilers would give you warnings about comparisons between
signed and unsigned values -- even though in this case, it's
completely intentional.
if (*s == c)

Another mandatory diagnostic here for the undeclared identifier 'c'.
return s;

...

}

I get 2 errors when compiling this:

error(212): return value type does not match the function type

Makes sense. You're trying to return a 'const char *' from a
function that expects to be returning a 'char *'. The other way
around works, of course, because you can legitimately "constify"
just about anything; but converting away 'const' is a Big No-No.
You shouldn't try it.
error(611): a value of type "const char *" cannot be assigned to an entity
of type "char *"

Again, duh. You can't blithely convert away constness, because that
basically destroys the safety of your code. The whole reason to
use 'const' is to protect variables from being changed arbitrarily;
if you could cast that away, then you could get around 'const' with
no repercussions, and it would make bugs that much harder to find.
I'd understand a warning, but an error?

From the C Standard's point of view, that's a quality-of-implementation
issue. Your compiler probably has a way to turn down the warning level;
but it would be much neater (and certainly your boss would thank you)
if you simply changed the code to make it correct in the first place.
At the moment, it looks like a mess.

HTH,
-Arthur
 
J

Joachim Schmitz

Hi Pete

pete said:
I see an automatic variable and a parameter, both named s,
and external variables named src and c ?
Is that really the code ?
No, sorry, if should have been
char * foo (const char *src)

Bye, Jojo
 
J

Joachim Schmitz

Hi Athur

Arthur J. O'Dwyer said:
Most compilers I know will issue a (non-required) diagnostic for
this definition, as it shadows a parameter with the same name.
Well, sorry, that was a mistake on my side.
From the C Standard's point of view, that's a quality-of-implementation
issue. Your compiler probably has a way to turn down the warning level;
but it would be much neater (and certainly your boss would thank you)
if you simply changed the code to make it correct in the first place.
At the moment, it looks like a mess.
As wrote elswhere in this thread, it isn't my code, it's a snippet from
Samba....
And no, my compiler doesn't have a switch to ignore errors, I can turn down
warnings, but not errors.
The only 'switch' would be a (char *) cast.
HTH,
-Arthur
Bye, Jojo
 
P

pete

Joachim said:
Hi Pete


No, sorry, if should have been
char * foo (const char *src)

I can only guess that there are more yet undisclosed typos.

If you have copy and paste capability, you should use it.

char * foo (const char *src)
{
const char *s; /* This should not cause a problem */

s = src;
return (char *)s;
/* This cast is needed, to shed the const qualifier */
}
 
D

Dan Pop

Most compilers I know will issue a (non-required) diagnostic for
this definition, as it shadows a parameter with the same name.

Non-required?!?

9 Each parameter has automatic storage duration. Its identifier
is an lvalue, which is in effect declared at the head of the
compound statement that constitutes the function body (and
therefore cannot be redeclared in the function body except in
an enclosed block).

Dan
 
A

Arthur J. O'Dwyer

Non-required?!?

9 Each parameter has automatic storage duration. Its identifier
is an lvalue, which is in effect declared at the head of the
compound statement that constitutes the function body (and
therefore cannot be redeclared in the function body except in
an enclosed block).

Hmm... I guess a diagnostic is required, then. Maybe I was confusing
this situation with the superficially-similar case in C++, where one
can write

[C++]
class foo {
int i;
void member_fxn();
};

void foo::member_fxn() {
int i;
/* ...'i' now refers to local 'i', not 'this->i' */
}
[/C++]

Anyway, required or not, this diagnostic shouldn't be ignored,
because it's so easy to fix it. ;-)

-Arthur
 

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

No members online now.

Forum statistics

Threads
474,140
Messages
2,570,810
Members
47,357
Latest member
sitele8746

Latest Threads

Top