234 views

How char *const  and const char* differ

| 234 views

Copying a portion of C grammar for declarations:

 declaration : declaration_specifiers ';' | declaration_specifiers init_declarator_list ';' ;
 declaration_specifiers : storage_class_specifier | storage_class_specifier declaration_specifiers | type_specifier | type_specifier declaration_specifiers | type_qualifier | type_qualifier declaration_specifiers | function_specifier | function_specifier declaration_specifiers ;
 storage_class_specifier : TYPEDEF | EXTERN | STATIC | AUTO | REGISTER ;
 type_specifier : VOID | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | SIGNED | UNSIGNED | BOOL | COMPLEX | IMAGINARY | struct_or_union_specifier | enum_specifier | TYPE_NAME ;
type_qualifier
: CONST
| RESTRICT
| VOLATILE
;

 declarator : pointer direct_declarator | direct_declarator ;
direct_declarator
: IDENTIFIER
| '(' declarator ')'
| direct_declarator '[' type_qualifier_list assignment_expression ']'
| direct_declarator '[' type_qualifier_list ']'
| direct_declarator '[' assignment_expression ']'
| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
| direct_declarator '[' type_qualifier_list '*' ']'
| direct_declarator '[' '*' ']'
| direct_declarator '[' ']'
| direct_declarator '(' parameter_type_list ')'
| direct_declarator '(' identifier_list ')'
| direct_declarator '(' ')'
;

 init_declarator_list : init_declarator | init_declarator_list ',' init_declarator ;
 init_declarator : declarator | declarator '=' initializer ;
 pointer : '*' | '*' type_qualifier_list | '*' pointer | '*' type_qualifier_list pointer ;
 type_qualifier_list : type_qualifier | type_qualifier_list type_qualifier ;

Full list:

So, "const" is a type qualifier and in a declaration a type qualifier can come alone or followed by declaration specifier. ( "const; " is a valid C statement as per C grammar).

Now see the "declarator". After a pointer we can have any number of type quantifiers. i.e.,

char * p, char * const p, char * const const p;

etc.

const char *p1 = "hello";
const * char p1 = "hello";
char const * p1 = "hello";
char * const p1 = "hello"

There are 4 ways we can write "const" and "char" involving a pointer. The thing to identify is whether "pointer" is constant or if it is a normal pointer to a "const char".

If pointer is "const", it cannot point to anything else and must be initialized (assigned a value along with declaration).

If pointer is to a character constant, then the location pointed to by the pointer cannot be modified. (If modified result is undefined meaning anything can happen).

So, lets see the 4 options I gave:

1. Constant character pointer, p1 - yes, p1 is a pointer to a constant char.
2. After "*" we cannot have a type specifier - hence invalid.
3. Character constant pointer, p1 - p1 is a pointer to a character constant - same as 1.
4. Constant pointer to character, p1 - p1 is a constant pointer to a character.

So, now coming to question:

p1 is a pointer to a character constant - (*p1) is READ ONLY

p2 is a constant pointer - p2 is READ ONLY.

So, statements 4 and 5 are not allowed.

by Veteran (425k points)
selected by

const char* p1 ---> This means that the string is constant . so it is stored in a read area in memory . so we cannot change its contents or edit it . Hence , if we dare to change the contents of this string , it will throw compiler error , but pointer can point to any other string .

char* const p2 ---> This means that the pointer is constant so it cannot point to any other string but if we want to change the contents of the string , we can as it is not constant .

Now, stm 3 , P1 wants to point to other string which is allowed and hence no error.

In stm 4 , P2 wants to point to other string , which results in an error .

Stm 5 is an error bcoz, P1 cannot edit the contents of constant string .

Stm 6 has no error , as P2 can change the contents of the string .

by Veteran (50.7k points)
0
Hi kapil I have a confusion here in stm 5 which is *(p1+3) = 'A'

as you said in your explanation that Stm 5 is an error bcoz, P1 cannot edit the contents of constant string .But actually here we are not editing anything

but if you see here p1 is a pointer here in which we are adding some integer *(p1+3) which is perfectly legal .and then memory address of A which is stored in memory somewhere we are assigning that address to pointer at location *(p1+3)...So why would it throw an error.
0
@shekhar sir ,

Here , P1 is a pointer which holds the base address of stm 1 string . so P1 will contain the address as it value inside it .
Now , in this base address , we add 3 take(3000 + 3 = 3003)

then *(3003) has to be given the value A, so we only change a character in this stm 1 string , which is definitely not allowed ,as it is stored in read area , we cannot write anything...
0
are we changing anything here ? I guess no see

if character pointer have a array A of string constant like this     K       A       P         I       L

100     200   300     400    500

and if pointer p1 is pointing to K then then pointer *p1 =&A      it is going to get the 100

if we do p1+3 then pointer p1 going to point  3 elements beyond the first element which is 400

means no *p1 =&(A+3) right ?   now if we do *(p1+3) = "A"    .nothing wrong in it

in case of string constant only problem is we can't change the value but if a pointer pointing to it and holding the address of a location 'A' then what is wrong in it.

I am not asking to edit  or assign anything I am just asking to hold the value of some location by a pointer ...what is wrong in it ?
0
sir,

can u plz tell me the answer...?

char* p = "kapil" ;

char p[ ] = "kapil" ;

p[3] = ' p ' ;// or we can say *( p + 3) ='p'

for both we apply this , what is the difference ?
0
first is a char pointer which points to the string constant but p will points to the starting of the array .

second one is the array of char but in this we can change any char. but not in the upper case .

there is no difference b/w p[3] ='p' and *(p+3) ='p' because starting of an array can be used as a pointer ..
0

u r right , there is not difference in writing .

The first one creates a pointer and sets it to the address of a constant string (assume in a region that does not have write protection on pages). Writing to this pointer is illegal and will probably crash. hence , we write const before it , to show that yes it is constant .

The second one creates an array and copies characters into it. Writing to this array will write to some location on stack and is perfectly legal.