473,385 Members | 1,834 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

function (const char *) vs. function (char *)

In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.

So I'm curious why "const char *" would be desirable?

The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?

I'm curious if there is something I'm missing about "const char *" in
function prototypes. K&R doesn't mention anything about this (though
of course some of the library functions do use "const char *").

Thanks,

-AF

Nov 15 '05 #1
8 10026

an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)
.... So I'm curious why "const char *" would be desirable?
So that you don't accidentally modify the value. Also, it allows a
caller to pass a const char * as an argument. Not to mention it
demonstrates to anyone using the function that it's not going to modify
their string if they care about it.
The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?


The pointer value is passed by value, but the contents of the string,
the characters, are not. The const keyword applies to the chars, not
the pointer.

Nov 15 '05 #2
an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);
Whoever told you that didn't know C. The type of "String"
is `char*', not `const char*', so you can pass it to myfunc()
(either edition) without any trouble.

(Why isn't "String" a `const char*'? Historical reasons:
pre-Standard C had no `const', so all functions with string
arguments looked like your original no matter whether they
intended to modify the string argument or not. If the Standard
had made character literals `const*', all pre-existing functions
would have suddenly become unable to accept string literals as
arguments. This would have raised a serious barrier to the
adoption of the Standard -- and the writers of the Standard were,
naturally, not interested in raising such barriers.)
However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.
As it should. Now that you know that "String" is not
const-qualified, you surely understand why.
So I'm curious why "const char *" would be desirable?
Mostly as documentation: A function that describes its argument
as `const char*' is promising not to modify the pointed-to string,
while a function that takes a plain `char*' either (1) leaves the
question open if it's "old code," or (2) suggests that it actually
may modify the string.

Unfortunately, the "promise" of `const char*' is violable. You
could perfectly well write a function like

void myfunc(const char *unmodifiable) {
char *gotcha = (char*)unmodifiable;
*gotcha = '\0';
}

.... thus in a sense lying to your clients. The language permits
such things -- it pretty much has to, if functions like strchr()
are to be written in C -- but, of course, You would Never do Such
A Thing. I hope. Use `conat char*' (more generally, `const T*')
whenever your function has no reason to want to modify the pointed-
to thing; use plain `char*' (`T*') when it might. The people who
write calls to your functions will thank you for your helpfulness.
The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?
Some of your language makes me a little queasy, and makes me
wonder if your grasp of C's argument-passing is as firm as it might
be. Remember always: The string itself is not "passed" to the
function, not ever. What the function receives is a pointer to the
first character of the string, while the string itself continues to
exist "outside." Since C uses call-by-value the function is free
to modify the pointer value it receives, and this modification will
not affect the caller. But even without modifying the pointer, the
function can use it to modify the pointed-to string -- except that
if the argument is `const'-qualified you've promised not to do so
(and the compiler will complain if you try, in the absence of the
sort of shenanigans shown above).
I'm curious if there is something I'm missing about "const char *" in
function prototypes. K&R doesn't mention anything about this (though
of course some of the library functions do use "const char *").


If you think `const' is hard to understand, just wait until
you encounter `restrict' ;-)

--
Eric Sosman
es*****@acm.org.invalid
Nov 15 '05 #3
Ian
an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.

So I'm curious why "const char *" would be desirable?

The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?

In these cases, you are passing a pointer by value, not what it points to!

So if you function takes a char*, it can and by implication, will modify
the data pointed to. This can give all sorts of undefined results if a
string literal is passed.

Ian
Nov 15 '05 #4
an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written
that looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.


The cited reason is a poor one since (for historical reasons) the
type of string literals is char[], not const char[]. Modifying the
contents of a string literal invokes undefined behaviour, but
the sample will not illustrate this properly on some platforms.

A better example would be...

const char fixed[] = "This string won't or shouldn't change.";
myfunc(fixed);

If myfunc doesn't attempt to modify the character array, then
making the parameter point to a const qualified character will
make your code arguably more robust. Why? Because if you do
accidentally(?!) modify the array using your parameter pointer,
then the compiler is required to issue a diagnostic (warning/
error.) So the const potentially guards against some logic
errors.

That said, there are some arguments against using const at
all in C. [Google for 'const poisoning', and check out the
reasons why functions like strpbrk (et all) take a const
qualified pointer, but return a non-const pointer.]

--
Peter

Nov 15 '05 #5

an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.

So I'm curious why "const char *" would be desirable?

Like others pointed out there is really nothing wrong in not
using const. But gcc (assuming you are using it) will emit
warnings if you turn on -Wwrite-strings.
Google for "initialization discards qualifiers" and you can find more
info

Karthik
The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?

I'm curious if there is something I'm missing about "const char *" in
function prototypes. K&R doesn't mention anything about this (though
of course some of the library functions do use "const char *").

Thanks,

-AF


Nov 15 '05 #6
On Tue, 23 Aug 2005 20:59:41 -0400, Eric Sosman wrote:
an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);
Whoever told you that didn't know C. The type of "String"
is `char*', not `const char*', so you can pass it to myfunc()
(either edition) without any trouble.


The type of "string" is char [7], it is an array of char not a pointer. Of
course like other arrays it is converted to a pointer to its first element
in most contexts including when used as a function argument.


(Why isn't "String" a `const char*'? Historical reasons:
pre-Standard C had no `const', so all functions with string
arguments looked like your original no matter whether they
intended to modify the string argument or not. If the Standard
had made character literals `const*', all pre-existing functions
would have suddenly become unable to accept string literals as
arguments. This would have raised a serious barrier to the
adoption of the Standard -- and the writers of the Standard were,
naturally, not interested in raising such barriers.)
However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.
As it should. Now that you know that "String" is not
const-qualified, you surely understand why.
So I'm curious why "const char *" would be desirable?


Mostly as documentation: A function that describes its argument
as `const char*' is promising not to modify the pointed-to string,
while a function that takes a plain `char*' either (1) leaves the
question open if it's "old code," or (2) suggests that it actually
may modify the string.


But it is "documentation" that the compiler can check to some degree. If
you have a pointer variable in your function of type const char * you cn
pass it directly to a function that takes a const char * argument but not
to one that takes a char * argument. Similarly for a const array of char
although that isn't as common.
Unfortunately, the "promise" of `const char*' is violable. You
could perfectly well write a function like

void myfunc(const char *unmodifiable) {
char *gotcha = (char*)unmodifiable;
*gotcha = '\0';
}

... thus in a sense lying to your clients. The language permits
such things -- it pretty much has to, if functions like strchr()
are to be written in C -- but, of course, You would Never do Such
A Thing. I hope. Use `conat char*' (more generally, `const T*')
whenever your function has no reason to want to modify the pointed-
to thing; use plain `char*' (`T*') when it might. The people who
write calls to your functions will thank you for your helpfulness.


Right, it is a matter of the interface specification. It is a normal
convention that when a function takes a pointer to const argument it won't
attempt to modify what the pointer points at. If this is the convention
used and the called function breaks it then the called function is broken.
As you say const here is documentation, but it provides some enforcable
checks, although not complete guarantees. The called function typically
has to use a nasty/suspicious construct like a pointer cast to get around
it.

Because string literals are not modifiable passing one to a function
taking a pointer to non-const char should be considered suspicious but
this is something you have to check yourself because it is valid as far as
C is concerned, or you find a compiler or lint tol that check for it as
something extra.

Lawrence
Nov 15 '05 #7
an***********@gmail.com writes:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.

So I'm curious why "const char *" would be desirable?


In cases where a parameter can be made 'const char *' rather
than just 'char *', and that doesn't affect the return type
of the function (or other similar kinds of ripple effects),
I almost always prefer to make the parameter the more
restrictive (that is, const) type.

The reason is, besides giving more guarantees to clients
about what will be done with what their pointer points to,
it makes it easier to crank up the compiler warning levels
so string literals may effectively be marked 'const' without
producing any diagnostics.

When there are ripple effects with function return type or
sometimes some other function return type, the decision
needs to be made on a case-by-case basis. Usually though
the cost of this sort of refactoring isn't too high, and it
results in finding defects reasonably often, so mostly using
'const' for pointer parameters seems like it's a win.
Naturally there are the occasional exceptions.
Nov 15 '05 #8
an***********@gmail.com wrote:
In a different newsgroup, I was told that a function I'd written that
looked like this:

void myfunc (char * somestring_ptr)

should instead be

void myfunc (const char * somestring_ptr)

When I asked why, I was told that it facilitated calling it as:

myfunc ("String");

instead of

strcpy (string, "What I want");
myfunc (string);

However, now that I experiment with it, I find that my original
prototype

void myfunc (char * somestring_ptr)

works perfectly well with either invocation.

So I'm curious why "const char *" would be desirable?

The only difference I see it makes is that it forbids modification of
the string within the function...of course, you can't modify the
original copy of the string, since C is call-by-value, but I guess
const char * means you can't modify the passed copy in the function
either...perhaps this is just an additional safeguard?


C is pass-by-value, yes, but the value passed is a pointer to the string
data. So, for example if you did:

void myfunc(char *ptr) {
ptr[0] = 'b';
}

/* ... */
char buf[4];
strcpy(buf, "foo");
myfunc(buf);
puts(buf); // prints boo
myfunc("foo"); // Undefined behavior; maybe crash, maybe worse

With const char *, changing ptr[0] would be forbidden.

--
λz.λi.i(i((λn.λm.λz.λi.nz(λq.mqi))((λn.λz .λi.n(nzi)i)(λz.λi.i(((λn.λz.λi.n
(nzi)i)(λz.λi.i(iz)))zi)))((λn.λz.λi.n(nzi)i) (λz.λi.i(iz)))zi))
Nov 15 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

30
by: Tim Johansson | last post by:
I'm new to C++, and tried to start making a script that will shuffle an array. Can someone please tell me what's wrong? #include <iostream.h> #include <string.h> int main () {...
5
by: TechCrazy | last post by:
What do each of these mean? Thanks. I am incredibly confused. char foo (const char * &p ); char foo (const char &* p ); char foo (const &char * p ); char foo (const char...
5
by: Johnathan Doe | last post by:
Why is is necessary to write a function that allocates memory for, or changes, a pointer to a char array using char** instead of char*? E.g. void modify_string( char** string ) { if( string...
34
by: Perro Flaco | last post by:
Hi! I've got this: string str1; char * str2; .... str1 = "whatever"; .... str2 = (char *)str1.c_str();
7
by: Eric | last post by:
Hi For this code, int getopt (int argc, char *const argv, const char *opts) what does the "char *const argv" mean? Does it equal to "char **const argv"? Or "char *const *argv"? Which is the...
4
by: Alan | last post by:
How do I convert the type const char* to type char*? I have an input string ("input_string") of class string. I need to convert this to type char* in order to use it in a call to the strtok()...
9
by: Peithon | last post by:
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...
14
by: Wolfgang | last post by:
As I understand, a const member function is used by const object to ensure that its instance isn't modified throughout its life. Am I missing something.. #include <iostream> using namespace...
11
by: john | last post by:
Hi, at first the code doesn't seem to work. Any ideas?: #include <iostream> #include <cstdlib> int main() { using namespace std;
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.