Why doesn't strcpy use a const pointer for dest? - c

Is there a reason strcpy's signature is this:
char *strcpy(char *dest, const char *src);
instead of this?
char *strcpy(char *const dest, const char *src);
As far as I know, the function will never change the pointer.
Am I misunderstanding what const pointers should be used for? In my mind, when a function I write accepts a pointer which won't be changed (via realloc, etc.), then I mark it as a const pointer so the caller can be assured their pointer won't be moved on them. (In case they have other structs/etc. referencing that pointer location that would become outdated)
Is that an OK practice, or will it have unintended consequences?

The source code for strcpy is very roughly this:
char *strcpy(char *dest, const char *src)
{
while (*dest++ = *src++);
}
Here we actually do modify dest but this has no consequence for the caller because inside the strcpyfunction, dest is a local variable.
But following code won't compile because dest is const:
char *strcpy(char * const dest, const char *src)
{
while (*dest++ = *src++);
}
we would need to write this:
char *strcpy(char * const dest, const char *src)
{
char *temp = dest;
while (*temp++ = *src++);
}
which introduces a non necessary temp variable.

Qualifiers on function arguments are completely ignored in declarations (prototypes). This is required by the C language, and it makes sense, because there is no possible meaning such qualification could have to callers of the function.
In the case of const char *src, the argument src is not what's qualified; the type it points to is qualified. In your hypothetical declaration for dest, the qualifier applies to dest and is thus meaningless.

char *foo(char *const dest, const char *src) { ... } means the pointer dest will not change in the body of the function.
It does not mean the data pointed to by dest will or will not change.
const char *src assures the calling code that the data pointed to by src will not change.
In calling a function like strcpy(d,s) or foo(d,s), the calling code does not care if the function changes its copy of the pointer. All the calling code cares about is if the data pointed to by s or d is changed and that is control by the const of the left side of *
char *dest, // data pointed by `dest` may or may not change.
const char *src // data pointed by `src` will not change change because of `src`.

It is meaningless to mark it as const as you suggest. In C, function arguments are passed as copy. It means that the variable dest inside strcpy() is actually a new variable (pushed on the stack), which holds the same content (here, the address).
Look at this function prototype:
void foo(int const a);
This has no semantic value, because we know that the original variable a that we passed to foo() can't be changed because it is a copy. Only the copy will potentially change. When foo return, we are guaranteed that the original variable a is unchanged.
In function parameters, you want to use the keyword const only if the function could actually persistently change the state of the variable. For example:
size_t strlen(const char *s);
This marks the content of the variable s (ie, the value stored at the address s points to) as const. Therefore, you are guaranteed your string will be unchanged when strlen returns.

As far as I know, the function will never change the pointer.
Yes, but you can. You are free to change the pointer. No need to make dest pointer const.
For example:
int main(void)
{
char *s = "Hello";
char *d = malloc(6);
strcpy(d, s);
puts(d);
strcpy(d, "World");
puts(d);
}

Related

function works ok w/o "const" flag. importance of "const"?

The function below uses const char *s1
What the function does is perhaps not important. It returns 1 if the string
contains characters other than allowed characters. It returns 0 if it
doesn't.
int TEST (const char *s1);
int TEST (const char *s1) {
char * s2= "o123";
return s1[ strspn(s1, s2) ] != '\0';
}
The function seems to work just fine if I were to remove const portion from it.
Why do I need const terminology in that function, if it seems to work fine without it? What is the importance of it? What are the implications of
using?
not using?
When you have const char *s1 you are telling the compiler that you will not modify the contents of the memory that s1 is pointing to. It's a semantic signal for the compiler so you do not make mistakes in the function (attempts to change the contents will results in errors). It might also allow the compiler to add some optimizations.
But more importantly it's a signal to other programmers reading your code, and using your function. And with "other programmers" I also include you in a few weeks, months or years time, when you might come back to the code and have forgotten the details of it.
importance of “const”?
3 reasons:
Applicability
Code correctness
Speed
Consider what the calling code is allowed to do
int TEST_with_const(const char *s1);
int TEST_without_const(char *s1);
char *cs;
const char *ccs
...
TEST_with_const(cs); // allowed
TEST_with_const(ccs); // allowed
TEST_without_const(cs); // allowed
TEST_without_const(ccs); // fails to compile.
The last one fails because TEST_without_const(char *s1); is telling the outside world, I want a pointer to memory that I might alter. ccs is not a pointer to modifiable memory.
Assuming TEST_without_const(char *s1); has the same body of int TEST (const char *s1), it did not need a pointer to modifiable memory
By using const char *s1 the function's body will complain during compilation should a modification of the memory pointed to by s1 is attempted. If the function design does not need to modify the memory pointed to by s1, this check helps insure correctness.
Depending on complier, some optimizations can occur with const char *, but not with char *.
const in this function prevents you to write something to memory where variable points to.
Here, you are only checking value if it is not equal to \0 and it is ok because you do only read operation.
int TEST (const char *s1) {
char * s2= "o123";
return s1[ strspn(s1, s2) ] != '\0';
}
If you do this, trying to write through s1 pointer:
int TEST (const char *s1) {
char * s2= "o123";
s1[0] = '4'; //Error, s1 is const pointer, can't write to memory pointed to by s1
return s1[ strspn(s1, s2) ] != '\0';
}
const pointer in your case means that this function should not write any data to input pointer, only read operation can be performed. You can in fact change where s1 points, only write to memory through s1 is not allowed. This is to prevent any mistakes to now write unexpectedly because it may in some cases lead to undefined behaviour.
The usage of const prevents you or somebody else working with your code from doing something accidentally wrong. Moreover it is for documentation purposes as the reader of the code knows that these functions are not changing the characters (read-only) the pointer points to.
Further the compiler may optimize your code if you use const correctness because it knows that these values are not changing inside the functions being read-only. But the first reason of documenting and making your function safer is more important.
There are three forms you always come accross with: char* s1, const char* s1 and const char* const s1. The forth but rarely needed form is: char* const. The meanings are as follows:
1.
char* s1:
In this case s1 is just a pointer to memory of one or more characters.
The following can be/can not be done inside of the function:
/* Function might changes content of s1 */
int TEST (char* s1)
{
s1[0] = 'A'; /* works */
*s1 = 'A'; /* same as above works */
++s1; /* this works because the copy of the pointer is non constant */
...
}
The following calls can be/can not be made:
char* str;
const char* const_str;
...
TEST(str); /* works as str as no restrictions */
TEST(const_str); /* fails because function might change const const_str */
2.
const char* s1:
The term: const char* s1 means s1 is a pointer to memory of one or more characters that can't be changed with this pointer. The following can be/can not be done inside of the function:
/* Function is read-only and doesn't changes content of s1 */
int CONST_TEST (const char* s1)
{
s1[0] = 'A'; /* compiler fail */
*s1 = 'A'; /* same as above compiler fail */
++s1; /* this works because the copy of the pointer is non constant */
...
}
The following calls can be/can not be made:
char* str;
const char* const_str;
...
CONST_TEST(str); /* works as str as no restrictions */
CONST_TEST(const_str); /* works because function is read-only and const_str is it also */
The compiler will fail compiling and tell you that you try to write to a memory location that is marked as constant.
3.
const char* const s1:
This means: s1 is a constant pointer to memory of one or more characters that can't be changed with this pointer. This is an extension to the first approach, the pointer s1 itself is passed by value and this copy can't be changes inside the function. So that you can not do something like ++s1 inside the function, therefore the pointer will allways point to the same memory location.
4.
char* const s1:
This is like case 3 but without s1 pointing to memory marked as constant. Therefore the content s1 is pointing to can be changed like case 1 but with a pointer being constant.

strcpy() implementation.. How to initialize a passing pointer to a function in the function itself

I'm trying to implement strcpy() standard function, as a function taking two pointers to characters and returning nothing.
I've done the job right, but to avoid segmentation fault I had to initialize "dest" pointer in the main function before assigning it to the strcpy() function. I've tried to do this initialization in the strcpy() function itself but couldn't because I'm sending the pointer (the address of the characters) by value, so I can't change it in the function although I can change what the pointer points to not the point itself.
May be a solution to pass a pointer to pointer to the strcpy() function, but I want it to act like the standard function, taking pointers to character not a pointer to pointer.
Concisely, how can I avoid segmentation fault by initializing the pointer in the strcpy() function itself not in the main function?
I hope my question is clear
Here is my code :
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void myStrcpy(char *dest,const char *src){
while(*src)
{
*dest = *src;
dest++;
src++;
}
*dest='\0';
}
int main(void){
char *src="Salahuddin";
int len=strlen(src);
char *dest=(char*)malloc(len);
myStrcpy(dest,src);
printf("%s",dest);
return 0;
}
Indirection only goes one-way. You cannot change the pointer unless you pass its address in or return a value to it.
You cant without changing the signature of the API.
You can declare your function as
void myStrcpy(char *&dest,const char *src)
^ look here!
It will solve this problem
May be a solution to pass a pointer to pointer to the strcpy()
function, but I want it to act like the standard function, taking
pointers to character not a pointer to pointer.
Why couldn't you do this?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void myStrcpy(char *dest, const char *src)
{
if (dest == NULL) {
dest = (char *) malloc(strlen(src));
}
while(*src) {
*dest = *src;
dest++;
src++;
}
*dest='\0';
}
int main(void)
{
char *src="Salahuddin";
int len=strlen(src);
char *dest=NULL;
myStrcpy(dest, src);
printf("%s", dest);
return 0;
}
You could also use the calloc function instead of malloc, which automatically initializes the allocated memory to '\0'.
Of course, you have to be careful and make sure you free your memory in either scenario... but you should be able to allocate the memory in the function.
Responding to this only: I'm trying to implement strcpy() standard function, as a function taking two pointers to characters and returning nothing.
If that first sentence is an accurate representation of what you really want,
Then write a wrapper around strcpy():
int main(void)
{
char *dest;
char src[] = {"some string");
dest = calloc(sizeof(src), sizeof(char));
myStrcpy(dest, src);
//use dest
free(dest);
return 0;
}
void myStrcpy(char *dest, char *src)
{
strcpy(dest, src);
}
This is bare bones, but with some error checking, it will do what you described in your intro sentence.

const char * VS char const * const (Not about what is const)

So, I know the differences between char const *, char * const, and char const * const. Those being:
char* the_string : I can change the char to which the_string points,
and I can modify the char at which it points.
const char* the_string : I can change the char to which the_string
points, but I cannot modify the char at which it points.
char* const the_string : I cannot change the char to which the_string
points, but I can modify the char at which it points.
const char* const the_string : I cannot change the char to which
the_string points, nor can I modify the char at which it points.
(from const char * const versus const char *?)
Now, my question is: Let's say I'm writing a function that would not modify the C string that is passed to it, for example:
int countA(??? string) {
int count = 0;
int i;
for (i=0; i<strlen(string); i++) {
if (string[i] == 'A') count++;
}
return count;
}
Now, what should the header be?
int countA(char const * string);
int countA(char const * const string);
My feeling is that I should use the second one, because I'm not going to modify the pointer itself, neither the contents of the array. But when I look to the header of standard functions they use the first one. Example
char * strcpy ( char * destination, const char * source );
Why?
(In fact char const * doesn't really make sense to me, because if you're thinking about the abstract string, either you are not modifying the string (so, char const * const because you are not modifying the pointer, neither the contents) or you will modify the string (so just char * because, you may modify the contents and you may need to allocate more memory, so you may need to modify the pointer)
I hope someone can make all this clear to me. Thanks.
In this case, it does not matter whether the pointer itself is const or not, because it is passed by-value anyway: Whatever strcpy does to source will not affect the caller's variable, because strcpy will operate on a copy of the caller's source on the stack, not the original. Note I am talking about the pointer value, not what the pointer points to, which should obviously not be changed since it is the source parameter.
char dest[10];
char const * source = "Hello";
strcpy( dest, source );
// no matter what strcpy does, the value of source will be unchanged
Within strcpy, you need to iterate pointers over the arrays pointed to by destination and source anyway. Not declaring the parameters as const allows the function to use the values from the stack directly, without copying / casting them first.
Having const char * represents a contract. It's a promise the function will not use that pointer to modify the contents passed by the user. Whether the pointer itself is constant or not is less valuable.
So, for the caller, whether the pointer itself is const or not makes no difference whatsoever.
In many implementations "string" functions regularly modify the passed pointer without modifying the contents. If the spec (the C standard) would mandate the pointer itself to be constant, it would be a limiting factor for all implementations, without providing any benefit for the caller.
As a side note, I think you shouldn't make everything const and then work your way around it. Just make stuff const if it feels the function shouldn't have reason to change it. In short, don't go const-mad, it's not a silver bullet and can be a recipe for frustration.
When you declare a function parameter as const char * const, it is not different to your callers from const char *: they could not care less what you do with that pointer, because to them it is all "pass by value" anyway.
The second const is there for you, not for your users. If you know that you are not going to modify that pointer, then by all means declare it const char * const: it is going to help you and others who maintain your code to catch errors later.
As for the standard library, my guess is that they did not want to make it const char * const because they wanted an ability to modify the poitners:
char * strcpy ( char * destination, const char * source ) {
char *res = destination;
while (*destination++ = *source++)
;
return res;
}
The non-defining declarations:
int countA(char const * string);
int countA(char const * const string);
int countA(char const * foobar);
int countA(char const *);
are all equivalent. The string parameter names (in effect) a local variable inside the implementation of countA. It's none of the caller's business whether the implementation modifies that variable or not, and it doesn't affect the signature of the function.
It is the caller's business whether the function modifies the referand of string, so the first const is important. It is slightly the caller's business what the variable is named, but only because the convention is to name parameters in declarations as a hint what they're used for. Documentation is the way to completely convey the meaning of each parameter, not its name.
If you want a rule: omit the second const, because it clutters the declaration while telling the caller nothing of any use.
You could include it in the function definition, but there are some problems with doing so. You either need to keep the header up to date with the definition (in which case you'll sometimes find yourself changing the header due to a change in implementation details that doesn't affect callers). Or else you have to accept that the header doesn't match the definition, which will occasionally upset people who see:
int countA(char const * const string) {
return 0;
}
and search the headers for int countA(char const * const string), or vice-versa see the header and search the source. They need a smarter search term.
char const *s : s is a pointer to const char.
char *const s : s is a constant pointer to char.
When s is a function parameter, the first notation is more useful than the second.
With char const *, you can't modify the pointed value.
With char *const, you can't modify the value of your pointer. It is like int const in function parameters : you can't do operations directly onto your parameter. It doesn't change anything for the call function. (now, it's almost useless for the compiler, but it's meaningful for programmers)

Why is the param of strlen a "const"?

I'm learning the C language.
My question is:
Why is the param of strlen a "const" ?
size_t strlen(const char * string);
I'm thinking it's because string is an address so it doesn't change after initialization. If this is right, does that mean every time you build a function using a pointer as a param, it should be set to a constant ?
Like if I decide to build a function that sets an int variable to its double, should it be defined as:
void timesTwo(const int *num)
{
*num *= 2;
}
or
void timesTwo(int *num)
{
*num *= 2;
}
Or does it make no difference at all ?
C string is a pointer to a zero-terminated sequence of characters. const in front of char * indicates to the compiler and to the programmer calling the function that strlen is not going to modify the data pointed to by the string pointer.
This point is easier to understand when you look at strcpy:
char * strcpy ( char * destination, const char * source );
its second argument is const, but its first argument is not. This tells the programmer that the data pointed to by the first pointer may be modified by the function, while the data pointed to by the second pointer will remain constant upon return from strcpy.
The parameter to strlen function is a pointer to a const because the function is not expected to change what the pointer points to - it is only expected to do something with the string without altering it.
In your function 'timesTwo', if you intend to change the value that 'num' points to, you should not pass it in as a pointer-to-const. So, use the second example.
Basically, the function is promising that it will not modify the contents of of the input string through that pointer; it says that the expression *string may not be written to.
Here are the various permutations of the const qualifier:
const char *s; // s may be modified, *s may not be modified
char const *s; // same as above
char * const s; // s may not be modified, *s may be modified
const char * const s; // neither s nor *s may be modified
char const * const s; // same as above

Accessing a C string from fixed Flash location

I have define a string at location 0xAABB:
const char str[] = "Hi There";
const word _Str1 #0xAABB = (word)str;
Now, I want to access this string located at 0xAABB.
What is the C syntax for this?
Just use a pointer to the memory location:
const char *str = (const char *)0xAABB;
Edit: (based on your comment) You need to first get the address from location 0xAABB and then use this value as the string's address:
const char *str = *(const char **)0xAABB;
This will dereference the pointer at 0xAABB to get the actual string address.
#define ADDRESS_OF_YOUR_STRING ((const char *)0xAABB)
const char *pointer_to_your_string = (const char *)0xAABB;
I could have used the macro in the pointer definition, but these are really intended to be separate demonstrations of how to do this. If you put the macro version in a header file and use it in your code the compiler will be able to optimize a little better. If you use a global pointer variable to access it then you may end up with the compiler needing to do an extra load of a pointer.
Using both of these is the same:
printf("%s\n", ADDRESS_OF_YOUR_STRING);
should work just fine since printf expects a pointer to a string for %s.

Resources