Is this legal?

K

Kelvin Moss

Hi all,

I am trying to call a library API that accepts a char* as one of the
parameter. In a particular mode this API never modifies the char*
variable. I am usually dealing with const char* strings (C style
strings). Is it safe to cast the const char* to char* in this
particular mode, rather than duplicating the original const char*
everytime ?

Thanks ..
 
C

Christopher Benson-Manica

Kelvin Moss said:
I am trying to call a library API that accepts a char* as one of the
parameter. In a particular mode this API never modifies the char*
variable. I am usually dealing with const char* strings (C style
strings). Is it safe to cast the const char* to char* in this
particular mode, rather than duplicating the original const char*
everytime ?

If you're sure that it never, ever modifies the char *, then sure, but
it's tantamount to

void api_call(char *foo) {
if( in_particular_mode ) {
work_fine();
}
else {
nuke_Moscow();
}
}

You, the current author, know that the library must be in a particular
mode for your code to work, but future maintainers may not. I would
personally prefer to wrap this API call in another method that takes a
const char * and creates a copy to pass to the library function,
unless you really can't afford the performance hit.
 
M

Michal Nazarewicz

Kelvin Moss said:
I am trying to call a library API that accepts a char* as one of the
parameter. In a particular mode this API never modifies the char*
variable. I am usually dealing with const char* strings (C style
strings). Is it safe to cast the const char* to char* in this
particular mode, rather than duplicating the original const char*
everytime ?

If you are 100% sure that the call will *never* modify the string nor
that it'll save the pointer somewhere and then at some time in the
future modify the string you should be safe casting to char*, however,
if that's the case the library is poorly written.
 
G

goose

Kelvin said:
Hi all,

I am trying to call a library API that accepts a char* as one of the
parameter. In a particular mode this API never modifies the char*
variable. I am usually dealing with const char* strings (C style
strings). Is it safe to cast the const char* to char* in this
particular mode, rather than duplicating the original const char*
everytime ?

No, it isn't safe. The reason I say this is because any function
that says in the prototype that it takes a "char *" rather than a
"const char *" is being very explicit about what it expects to get.

Don't rely on the documentation (which may get out of date) - rest
assured that the programmer who originally wrote that library will
one day leave and be replaced by a programmer who, during
maintenance, is going to say
"Hey, since we say we expect a char *, we can modify this
function to *always* modify the argument. Surely no one will
be passing us string literals as we are very explicit about
accepting
non-const char pointers."


Your best defence against library modifications is to write a
wrapper function:

char *wrapper (char *arg)
{
char *t = malloc (strlen (arg) + 1);
char *ret;
if (!t) {
return NULL;
}
strcpy (t, arg);
ret = libAPI_func (t);
free (t); /* For extra points, return the modified string instead */
return ret;
}

Remember, the whole idea of the prototype is to tell the caller
what datatypes the function can be legally called with. Other
assumptions
that are specified in a seperate document are a risk and should be
considered as such.

goose,
 
R

Random832

2006-12-04 said:
"Hey, since we say we expect a char *, we can modify this function
to *always* modify the argument. Surely no one will be passing us
string literals as we are very explicit about accepting non-const
char pointers."

String literals are not const.
 
C

CBFalconer

Random832 said:
String literals are not const.

But, if you mark all such as const (or use the gcc -Wwrite-strings)
you can avoid many gross errors. They are not const purely to
avoid conflict with ancient usage.
 
S

Simon Biber

goose said:
Your best defence against library modifications is to write a
wrapper function:

char *wrapper (char *arg)

I think the idea was to have the wrapper take a 'const char *arg'?
{
char *t = malloc (strlen (arg) + 1);
char *ret;
if (!t) {
return NULL;
}
strcpy (t, arg);
ret = libAPI_func (t);
free (t); /* For extra points, return the modified string instead */

Perhaps 'in addition', rather than 'instead'. The returned value from
libAPI_func may be significant.
 
G

goose

Random832 said:
String literals are not const.

(Damn :) But they *should* be!

Okay. I retract what I said above; change it to read:

"Surely no one will be passing us string literals
as we are very explicit about accepting writable
strings." ^^^^^^^^

goose,
(I tend to treat them as const, honest)
 
Y

Yevgen Muntyan

goose said:
No, it isn't safe. The reason I say this is because any function
that says in the prototype that it takes a "char *" rather than a
"const char *" is being very explicit about what it expects to get.

There are also legacy APIs which simply do not use const where they
should, for instance Python C API used char* everywhere until recently.
So it really depends.
Don't rely on the documentation (which may get out of date) - rest
assured that the programmer who originally wrote that library will
one day leave and be replaced by a programmer who, during
maintenance, is going to say
"Hey, since we say we expect a char *, we can modify this
function to *always* modify the argument. Surely no one will
be passing us string literals as we are very explicit about
accepting
non-const char pointers."

This case is rather qualified as intentional breaking user code. Docs
said function doesn't modify its argument and programmer makes the
function indeed modify the argument because of prototype?
Your best defence against library modifications is to write a
wrapper function:

This may not be an option. E.g. in case of Python, there are about two
zillion functions, you simply can't write wrappers for all of them. You
have to read docs, read sources, and hope for the best.
Remember, the whole idea of the prototype is to tell the caller
what datatypes the function can be legally called with.

Prototypes are what human programmer wrote, unfortunately, sometimes
they do not express function intentions clearly :)

Best regards,
Yevgen
 

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
473,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top