i want to ask a question about pointer:
void fun(const char** a) {...}
1.
const char* b = nullptr;
fun(&b);
2.
const char** b = nullptr;
fun(b);
why use 1 but not 2?
1 is good, 2 donnot work
C uses pass by value for function call arguments. That means a function receives a copy of the passed value, and there's no way for the function to directly change a variable in the caller.
For example, if you write
void set_to_5(int x)
{
x = 5;
}
and then write
int i = 3;
set_to_5(i);
printf("%d\n", i);
it prints 3, not 5. Or, if you write
void set_string(char *str)
{
str = "world";
}
and then write
char *p = "hello";
set_string(p);
printf("%s\n", p);
it prints hello, not world.
In both cases, the function successfully changes its copy of the passed value — x or str — but that doesn't have any effect on the variable in the caller (i or p).
When you want to have a function that does change a variable in its caller, one way to do that is to have the function accept a pointer. That looks like this:
void set_to_5_via_pointer(int *x)
{
*x = 5;
}
void set_string_via_pointer(char **str)
{
*str = "world";
}
Then you can write:
int i = 3;
set_to_5_via_pointer(&i);
printf("%d\n", i);
char *p = "hello";
set_string_via_pointer(&p);
printf("%s\n", p);
Now it does print 5 and world, as desired.
Notice that in each case I made three changes:
I added a * to the parameter type expected by the function (int x to int *x, char *str to char **str)
I added a * before each use of the parameter in the function, that is, where I actually set the new value (5 and "world")
I added a & before the variables where I passed them to the function (set_to_5_via_pointer(&i) and set_string_via_pointer(&p)).
One more thing. When you see a function declaration like
void set_string_via_pointer(char **str);
this does not necessarily mean that the right way to call the function is
char **x;
set_string_via_pointer(x);
Yes, here x is of type char **, and function set_string_via_pointer expects an argument of type char **, so it's a match. But if you declare and call
char *y;
set_string_via_pointer(&y);
that's also a perfectly good way to pass an argument of type char **, and in this case, it's certainly they way that was expected.
const char* b = nullptr;
fun(&b);
This passes the pointer b by reference — or emulates pass by reference semantics — i.e. the memory address of where the variable is stored is passed instead of its value. This allows you to access the pointer originally declared in the calling function, and any changes made to that pointer in the called function would be visible in the calling function.
const char** b = nullptr;
fun(b);
Au contraire, this passes b by value. If you change the pointer to point to some other memory location in the called function, that change will not be reflected back in the calling function. Any attempt to dereference it while it is pointing to NULL would result in undefined behaviour as per the following clauses of C11:
If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.
[...]
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, [...]
[6.5.3.2 Address and indirection operators, C11]
why use 1 but not 2?
Why use either of them?
1 is good, 2 donnot work
“There is nothing either good or bad, but thinking makes it so.” — They both serve different purposes. Though, the purpose of the second snippet is rather ambiguous here.
This code snippet
void fun(const char** a) {...}
1.
const char* b = nullptr;
fun(&b);
means passing the pointer b to the function fun by reference in the C meaning. So dereferencing the pointer to pointer a within the function you can change the original pointer b passed to the function indirectly through a pointer to it.
Here is a demonstration program.
#include <stdio.h>
void fun( const char **a )
{
*a = "Hello World!";
}
int main( void )
{
const char *b = NULL;
fun( &b );
puts( b );
}
The program output is
Hello World!
As you can see the pointer b is passed to the function indirectly through a pointer to it (by reference in the C meaning). Thus dereferencing the pointer to pointer a
*a = "Hello World!";
you can change the original pointer b defined in main.
In the second case
2.
const char** b = nullptr;
fun(b);
the pointer b is passed by value and if the function fun will dereference the null pointer then undefined behavior will be invoked.
Related
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 1 year ago.
I have a question about pointer.
Recently, I was looking some system programming tutorial. The teacher is talking about asprintf() Function.
According to the man page, the definition of asprintf() is:
int asprintf(char **ret, const char *format, ...);
However, I found that the teacher tends to create a single pointer and then pass the address of that single pointer to the first parameter. Like this:
int main()
{
char *buffer;
int r;
r = asprintf(&buffer,"The total is %d\n",5+8);
puts(buffer);
printf("%d characters generated\n",r);
return(0);
}
I am wondering why don't we declare double pointer and then pass that double pointer to the function, just like the definition.
In addition, the teacher use the same tricks in other function too, such as: getline()
Therefore, is there any advantage that we would choose single pointer over double pointer, even the definition of the function is double pointer?
Thanks for everyone for replying in advanced. :))
asprintf will allocate some memory and write the printf result into that memory.
To get this resulting memory buffer, you pass a pointer to a local variable (in your case: buffer) as the first argument. This pointer is then dereferenced in the function, to change the value of your local variable, so the code in asprintf semantically does something like this:
int asprintf(char **ret, const char *format, ...) {
*ref = malloc(some_size);
sprintf(*ret, format, ...);
}
What would now happen if you didn't have a local variable of type char * and passed a pointer to this variable, but instead had a local variable of type char **, like you suggested:
char **buffer;
asprintf(buffer, "The total is %d\n", 5+8);
Well, asprintf would again just dereference this pointer you just passed. But in this code, it doesn't yet point to anything meaningful, so this would result in an error. We must have enough memory allocated at the address we are passing to asprintf so it can store a char* there for us.
Now, this would work:
char *buffer;
char **pointer_to_buffer = &buffer;
asprintf(pointer_to_buffer, "The total is %d\n", 5+8);
but it is just more complicated and verbose.
But why do we do this whole pointer-to-pointer thing? Well, you would certainly first try to simply pass the pointer, instead of a pointer-to-pointer, like this:
char *buffer;
asprintf(buffer, "The total is %d\n", 5+8);
with asprintf semantically doing something like this:
int asprintf(char *ret, const char *format, ...) {
ref = malloc(some_size);
sprintf(ret, format, ...);
}
However, it is critical that here, buffer is passed by value. This means that when asprintf locally modifies ret, it modifies a copy of the value of our buffer. We, the caller, will not be able to see this change in our variable buffer. This is why we pass a pointer-to our local variable buffer, not the value itself.
I am wondering why don't we declare double pointer and then pass that double pointer to the function, just like the definition.
Because you want to update the value stored in buffer. The type of the expression &buffer is char **.
Remember, in order for a function to write to any of its parameters, you must pass a pointer to that parameter:
void foo( T *ptr )
{
*ptr = new_T_value(); // writes a new value of type T to the thing ptr points to
}
void bar( void )
{
T var;
foo( &var ); // writes a new value to var
}
Thus, the following are true:
ptr == &var // T * == T *
*ptr == var // T == T
IOW, writing to the expression *ptr is the same as writing to var.
So, why not just create a pointer variable in bar and pass it to foo? If we wrote something like
void bar( void )
{
T *vptr;
foo( vptr );
}
the problem is that vptr doesn't point to anything meaningful - we have
ptr == vptr // T * == T *
*ptr == *vptr == ??? // T == T == ???
There's no object of type T for us to update. Now, we could create another object for vptr to point to:
void bar( void )
{
T var;
T *vptr = &var;
foo( vptr );
}
and that will work as expected, but the extra pointer variable is redundant in this case.
The same logic holds for pointer objects - let's replace T with a pointer type, P *. Then our code becomes:
void foo( P * *ptr ) // or P **ptr
{
*ptr = new_P_star_value(); // writes a new value of type P * to the thing ptr points to
}
void bar( void )
{
P * var; // or P *var
foo( &var ); // writes a new value to var
}
which gives us
ptr == &var
*ptr == var == some_P_star_value
**ptr == *var == *some_P_star_value == some_P_value
Same thing as above - we want to write a new value to var. To do that we pass a pointer to it, even though var is already a pointer type. This is why multiple indirection exists in the first place.
Most of the time when you see a function that has a pointer or pointer-to-pointer parameter, it's expecting you to pass the address of another object (obtained with the & operator), not a pointer variable as such.
If you want to change an object used as an argument in a function you need to pass it by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer a function can get a direct access to the original pointer.
Consider this demonstrative program and compare the result of calls of the two functions f and g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f( char *s )
{
s = malloc( 14 );
strcpy( s, "Hello World!" );
}
void g( char **ps )
{
*ps = malloc( 14 );
strcpy( *ps, "Hello World!" );
}
int main(void)
{
char *s = NULL;
f( s );
if ( s != NULL ) puts( s );
else puts( "s is a null pointer." );
g( &s );
if ( s != NULL ) puts( s );
else puts( "s is a null pointer." );
free( s );
return 0;
}
The program output is
s is a null pointer.
Hello World!
The function f accepts the pointer s declared in main by value. It means that the function deals with a copy of the value of the pointer s. Changing the copy does not affect the original pointer s. So the function produces a memory leak because it allocates dynamically a memory and the address of the allocated memory stored in the local variable (function parameter) s will be lost after exiting the function.
The function g accepts the pointer s by reference through a pointer to it. So dereferencing its parameter the function has a direct access to the original pointer s and can change it.
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
I'm new to C, sorry if my question sound dumb.
I see some function takes a "double" pointer as parameter, for example:
int main(int argc, char **argv)
{
...
}
I can understand the need for a double pointer such as argv, since argv is the pointer to the first element of argument array whose element is also a pointer to a char type. double pointer is needed in this case.
But for some functions like:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
I don't understand why a double point is needed, since there is no array element involved, and I think getaddrinfo calls malloc internally, so it might be a reason to use double pointer, but we can have sth like this:
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char *ptr)
{
ptr = malloc(10);
}
so the parameter is a single pointer char * ptr, no char **ptr is needed?
Passing a pointer, or address of an object allows the value stored at that location in memory to be changed by the function, so when the function returns, the information stored at that address now contains updated values. Likewise if a function argument accepts a pointer variable, and the pointer variable is to be changed, the address to that pointer must be passed, thus requiring the function prototype to be a pointer-to-pointer.
Addressing your question may illustrate: getaddrinfo question: I don't understand why a double point is needed, since there is no array element involved
Usage for this struct is typically:
struct addrinfo *result;//pointer variable
getaddrinfo("hostname", "servicename", NULL, &result);
// |_Passing address of a pointer variable.
// thus requiring prototype to accommodate
So as explained, for the function to receive updated struct information, it needs to send the address of the pointer variable, requiring it to be a double pointer:
int getaddrinfo(const char *host, ..., struct addrinfo **result);
Your code is incorrect. ptr is local to the scope of test. A pointer is just a number representing a memory address. You probably wouldn't expect test in the following code to affect the value of number_main, right?
int main()
{
int number_main;
test(number_main);
printf("%d\n", number_main);
}
void test(int number_main)
{
number_main = 10;
}
Maybe it helps if you internalize char * as some fictional type you'll call number_that_represents_memory_address, which you then think about as no different than int in this case?
This function
void test(char *ptr)
{
ptr = malloc(10);
}
that shall be declared before its usage in main deals with a copy of the value of the passed argument in main
char *ptr_main;
test(ptr_main);
You can imagine the function call and the function definition the following way
char *ptr_main;
test(ptr_main);
//...
void test( /* char *ptr */ )
{
char *ptr = ptr_main;
ptr = malloc(10);
}
So as you can see within the function it is the local variable ptr that is changed. The argument ptr_main that was not initialized in main and has indeterminate value stays unchanged.
To change the original pointer ptr_main you have to pass it to the function by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it.
From the C Standard (6.2.5 Types)
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
So the function definition should look like
void test( char **ptr )
{
*ptr = malloc(10);
}
And called like
test( &ptr_main );
Thus dereferencing the pointer ptr in the function we get a direct access to the pointed object (pointer) ptr_main and it is the pointed (referenced) object that is changed now in the function
To make it more clear consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f1( int *px )
{
*px = 10;
}
void f2( int **ppx )
{
*ppx = malloc( sizeof( int ) );
**ppx = 20;
}
int main(void)
{
int x = 0;
printf( "Before calling f1 x = %d\n", x );
f1( &x );
printf( "After calling f1 x = %d\n", x );
int *px = &x;
printf( "Before calling f2 px = %p and *px = %d\n", ( void * )px, *px );
f2( &px );
printf( "After calling f2 px = %p and *px = %d\n", ( void * )px, *px );
free( px );
return 0;
}
The program output might look like
Before calling f1 x = 0
After calling f1 x = 10
Before calling f2 px = 0x7ffe79dd572c and *px = 10
After calling f2 px = 0x55db88f5d270 and *px = 20
To change the object x declared in main in the function f1 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
The same situation takes place with the pointer px. Pointers are objects. If we want to change the pointer px declared in main in the function f2 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
And as you can see from the program output the function f2 indeed changed the value of the pointer px declared in main.
This question already has answers here:
Passing char pointer in C
(5 answers)
Closed 6 years ago.
I'm trying to understand the difference between pass by value and pass by reference, and I thought that I finally understand it, until I saw this code :
void change(char *p1)
{
p1="new";
}
int main()
{
char *txt1=(char*)malloc(200*sizeof(char));
txt1="original";
printf("before :%s\n",txt1);
change(txt1);
printf("after :%s\n",txt1);
}
Isn't it passing an address ? and then changing it and making it point to somewhere else ?
The output is :
before : original
after : original
Why is that?
There is no pass-by-reference in C. Function parameters are passed using pass-by-value. That is, p1 itself is passed by value. You can change the content of the memory address pointed to by p1 (*p1) from the called function, not p1 itself.
To clarify, for changing the content of a variable var, you need to pass the address of var, so, if you want to change a pointer itself, you need to pass the address of the pointer to the function.
That said, please see this discussion on why not to cast the return value of malloc() and family in C.
This is passing an address as value. To have the callee modify caller's local variable, pass address of what should be modified.
#include <stdio.h>
void change(char **p1)
{
*p1="new";
}
int main(void)
{
char *txt1; /* no causing memory leak */
txt1="original";
printf("before :%s\n",txt1);
change(&txt1);
printf("after :%s\n",txt1);
}
Pass By Reference and Pass By value.
Here's an example I've used before. Assume the following two functions:
void foo( T *p ) // where T is an arbitrary data type
{
*p = new_value(); // write new value to the thing p points to
}
void bar( void )
{
T var;
foo( &var ); // write new value to var
}
For function foo to update the contents of var (an object of type T) we must pass a pointer to var (type T *).
If we replace T with a pointer type P *, then the above code becomes
void foo( P **p )
{
*p = new_value(); // write new value to the thing p points to
}
void bar( void )
{
P *var;
foo( &var ); // write new value to var
}
The semantics are exactly the same; we want foo to write a new value to var, so we pass a pointer to var. It's just that in this case, var is already a pointer type, so we wind up passing a pointer to a pointer.
Basically, for foo to update the contents of var, you must pass the expression &var as the argument, meaning the type of the formal parameter p will always have one more level of indirection than the type of var.
Type of var Type of &var Type of p
----------- ------------ ---------
T T * T *
T * T ** T **
T ** T *** T ***
etc.
In function call change(txt1);, txt1 is passed by value. It is copied to the parameter p of function change. This makes pi points to the same string as txt1 pointing to. When new string is assigned to p1 then p1 changes to point to that string while txt1 pointing previous one.
this case is very similar to
char *s1 = "String";
char *s2 = s1; // Both s1 and s2 points to same string
s2 = "Another string" // Now s2 points to "Another string" while s1 pointing to "String".
Beside that your code is causing memory leak. It should be like
char *txt1=(char*)malloc(200*sizeof(char));
strcpy(txt1,"original");
Why I can not change the content the char* points to?
For example:
int main(int argc, char * argv[]) {
char *a = NULL; // now a = NULL
b(a);
// but now a points to NULL again! Why?
}
void b(char *argv[], char* c) {
// now a is passed in
c = *argv[3];
// now a actually points to the start of char array pointed to by argv[3]
}
From the output, I see the *a is passed to the function. Then inside the function b, it actually pointed to the expected char[ ]. But when returned from b, a became NULL again. Why? And how can a points to expected content after return from b? Thank you!
C passes everything by value, including pointers. Function parameters are similar to local variables that acquire their initial value from the caller. Once you are inside the function, the value of the parameter can be changed freely without influencing the values passed by the caller.
C's way of passing modifiable stuff into a function is passing pointers. If you want to modify a value of some type T, you pass a pointer to T; if you want to modify a pointer to T, you must pass a pointer to a pointer to T, and so on. In other words, the level of indirection must be higher by one than that of the value being changed.
How does this apply to your case? Your function b needs to modify a pointer to char, hence it needs to take a pointer to a pointer to a char, like this:
void b(char *argv[], char **ppc) {
...
}
Inside the function you modify the pointer to which ppc points by dereferencing ppc once:
*ppc = argv[3]; // No asterisk here in front of `argv`
Of course calling b from the main needs to take the address of a, like this:
b(argv, &a);
This question already has answers here:
What is the difference between char * const and const char *?
(19 answers)
Closed 7 years ago.
What is the difference between the following declarations?
char * const a;
const char * a;
In order to understand the difference I wrote this small program:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
char a = 'x';
char b = 'y';
char * const pc1 = &a;
const char * pc2 = &a;
printf ("Before\n");
printf ("pc1=%p\n", pc1);
printf ("*pc1=%c\n", *pc1);
printf ("pc2=%p\n", pc2);
printf ("*pc2=%c\n", *pc2);
*pc1 = b;
/* pc1 = &b; */
/* *pc2 = b; */
pc2 = &b;
printf ("\n\n");
printf ("After\n");
printf ("pc1=%p\n", pc1);
printf ("*pc1=%c\n", *pc1);
printf ("pc2=%p\n", pc2);
printf ("*pc2=%c\n", *pc2);
return EXIT_SUCCESS;
}
I compiled the program (with gcc 3.4) and ran it. The output highlights the difference rather well:
Before
pc1=ffbfd7e7
*pc1=x
pc2=ffbfd7e7
*pc2=x
After
pc1=ffbfd7e7
*pc1=y
pc2=ffbfd7e6
*pc2=x
However, I had to write the small program to get the answer. In case I'm away from the machine (at an interview for instance), I wouldn't be able to answer the question.
Can someone please explain, by commenting the above example, how the const keyword operates?
char * const a;
means that the pointer is constant and immutable but the pointed data is not.
You could use const_cast(in C++) or c-style cast to cast away the constness in this case as data itself is not constant.
const char * a;
means that the pointed data cannot be written to using the pointer a.
Using a const_cast(C++) or c-style cast to cast away the constness in this case causes Undefined Behavior.
To parse complicated types, you start at the variable, go left, and spiral outwards. If there aren't any arrays or functions to worry about (because these sit to the right of the variable name) this becomes a case of reading from right-to-left.
So with char *const a; you have a, which is a const pointer (*) to a char. In other words you can change the char which a is pointing at, but you can't make a point at anything different.
Conversely with const char* b; you have b, which is a pointer (*) to a char which is const. You can make b point at any char you like, but you cannot change the value of that char using *b = ...;.
You can also of course have both flavours of const-ness at one time: const char *const c;.
char * const a;
*a is writable, but a is not; in other words, you can modify the value pointed to by a, but you cannot modify a itself. a is a constant pointer to char.
const char * a;
a is writable, but *a is not; in other words, you can modify a (pointing it to a new location), but you cannot modify the value pointed to by a.
Note that this is identical to
char const * a;
In this case, a is a pointer to a const char.
Now that you know the difference between char * const a and const char * a. Many times we get confused if its a constant pointer or pointer to a constant variable.
How to read it? Follow the below simple step to identify between upper two.
Lets see how to read below declaration
char * const a;
read from Right to Left
Now start with a,
1 . adjacent to a there is const.
char * (const a);
---> So a is a constant (????).
2 . Now go along you get *
char (* (const a));
---> So a is a constant pointer to (????).
3 . Go along and there is char
(char (* (const a)));
---> a is a constant pointer to character variable
a is constant pointer to character variable.
Isn't it easy to read?
Similarily for second declaration
const char * a;
Now again start with a,
1 . Adjacent to a there is *
---> So a is a pointer to (????)
2 . Now there is char
---> so a is pointer character,
Well that doesn't make any sense!!! So shuffle pointer and character
---> so a is character pointer to (?????)
3 . Now you have constant
---> so a is character pointer to constant variable
But though you can make out what declaration means, lets make it sound more sensible.
a is pointer to constant character variable
The easiest way to understand the difference is to think of the different possibilities. There are two objects to consider, the pointer and the object pointed to (in this case 'a' is the name of the pointer, the object pointed to is unnamed, of type char). The possibilities are:
nothing is const
the pointer is const
the object pointed to is const
both the pointer and the pointed to object are const.
These different possibilities can be expressed in C as follows:
char * a;
char * const a;
const char * a;
const char * const a;
I hope this illustrates the possible differences
The first is a constant pointer to a char and the second is a pointer to a constant char. You didn't touch all the cases in your code:
char * const pc1 = &a; /* You can't make pc1 point to anything else */
const char * pc2 = &a; /* You can't dereference pc2 to write. */
*pc1 = 'c' /* Legal. */
*pc2 = 'c' /* Illegal. */
pc1 = &b; /* Illegal, pc1 is a constant pointer. */
pc2 = &b; /* Legal, pc2 itself is not constant. */
I will explain it verbally first and then with an example:
A pointer object can be declared as a const pointer or a pointer to a const object (or both):
A const pointer cannot be reassigned to point to a different object from the one it is initially assigned, but it can be used to modify the object that it points to (called the "pointee").
Reference variables are thus an alternate syntax for constpointers.
A pointer to a const object, on the other hand, can be reassigned to point to another object of the same type or of a convertible type, but it cannot be used to modify any object.
A const pointer to a const object can also be declared and can neither be used to modify the pointee nor be reassigned to point to another object.
Example:
void Foo( int * ptr,
int const * ptrToConst,
int * const constPtr,
int const * const constPtrToConst )
{
*ptr = 0; // OK: modifies the "pointee" data
ptr = 0; // OK: modifies the pointer
*ptrToConst = 0; // Error! Cannot modify the "pointee" data
ptrToConst = 0; // OK: modifies the pointer
*constPtr = 0; // OK: modifies the "pointee" data
constPtr = 0; // Error! Cannot modify the pointer
*constPtrToConst = 0; // Error! Cannot modify the "pointee" data
constPtrToConst = 0; // Error! Cannot modify the pointer
}
Happy to help! Good Luck!
Above are great answers. Here is an easy way to remember this:
a is a pointer
*a is the value
Now if you say "const a" then the pointer is const. (i.e. char * const a;)
If you say "const *a" then the value is const. (i.e. const char * a;)
You may use cdecl utility or its online versions, like https://cdecl.org/
For example:
void (* x)(int (*[])());
is a
declare x as pointer to function (array of pointer to function returning int) returning void
Trying to answer in simple way:
char * const a; => a is (const) constant (*) pointer of type char {L <- R}. =>( Constant Pointer )
const char * a; => a is (*) pointer to char constant {L <- R}. =>( Pointer to Constant)
Constant Pointer:
pointer is constant !!. i.e, the address it is holding can't be changed. It will be stored in read only memory.
Let's try to change the address of pointer to understand more:
char * const a = &b;
char c;
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable.
It means once constant pointer points some thing it is forever.
pointer a points only b.
However you can change the value of b eg:
char b='a';
char * const a =&b;
printf("\n print a : [%c]\n",*a);
*a = 'c';
printf("\n now print a : [%c]\n",*a);
Pointer to Constant:
Value pointed by the pointer can't be changed.
const char *a;
char b = 'b';
const char * a =&b;
char c;
a=&c; //legal
*a = 'c'; // illegal , *a is pointer to constant can't change!.
const char * a;
This states pointer to constant character.
For eg.
char b='s';
const char *a = &b;
Here a points to a constant char('s',in this case).You can't use a to change that value.But this declaration doesn't mean that value it points to is really a constant,it just means the value is a constant insofar as a is concerned.
You can change the value of b directly by changing the value of b,but you can't change the value indirectly via the a pointer.
*a='t'; //INVALID
b='t' ; //VALID
char * const a=&b
This states a constant pointer to char.
It constraints a to point only to b however it allows you to alter the value of b.
Hope it helps!!! :)