Const Char & Char Const

T

tommyprep

Hi,

I am new to the C language. Got the doubt which is discussed
frequently.
I have the following piece of code which is compiled without
warnings and run Successfully.

Issue 1 : I can change the value pointed by const char *ptr_ch1;
Issue 2: I can change the Pointer location on char const *ptr_ch2.

/**** Output ****/
ptr_ch1 -> Y <<<<< This is Ok.
Modified ptr_ch1 -> G <<< Why compiler allowed it
without any warning.

ptr_ch2 -> O <<< This is OK
Modifed ptr_ch2 -> E <<< This is also OK
Modified Pointer of ptr_ch2 -> G <<<< Why again compiler
didn't give any error/warning.
/*****************/

Checked it in Linux GCC and DEV-C++

#include <stdio.h>
#include <stdlib.h>

int main ()
{
char ch1= 'Y';
char ch2='O';
const char * ptr_ch1 = &ch1;
char const *ptr_ch2 = &ch2;

printf ("\n ptr_ch1 -> %c \n", *ptr_ch1);

ch1 = 'G';
printf ("\n Modified ptr_ch1 -> %c \n", *ptr_ch1);

printf ("\n ptr_ch2 -> %c\n", *ptr_ch2);

ch2 = 'E';
printf ("\n Modifed ptr_ch2 -> %c\n", *ptr_ch2);

ptr_ch2 = &ch1;
printf ("\n Modified Pointer of ptr_ch2 -> %c \n", *ptr_ch2);

return 0;
}
 
T

Tomás Ó hÉilidhe

   Issue 1 : I can change the value pointed by const char *ptr_ch1;
   Issue 2: I can change the Pointer location on char const


You have a lot of freedom with word order in C. The following are
identical:

char const c = 5;
const char c = 5;

In order to create a pointer, you add an asterisk (i.e. *) to the name
of the object, as follows:

char const *p = &c;
const char *p = &c;

In order to assign attributes to the pointer itself, rather than to
the pointed-to object, you put the attributes /after/ the asterisk.
Examples:

char const *const p = &c;
= A const pointer to a const char

char const *const volatile p = &c;
= A volatile const pointer to a const char

char const *volatile p = &c;
= A volatile non-const pointer to a const char

There's three attributes you can assign to a pointer: const volatile
restrict. That last one, "restrict", was brought in with C99. You can
use restrict as much as you like, because if you need to compile with
a C89 compiler you simply have to do:

#define restrict /* nothing */

I do something similar with "inline" on C89 compilers:

#define inline static

(but you've to be careful with this one if an inline function contains
a static object)
 
T

tommyprep

Assigning the address of one object to a (const char *) pointer,
only protects the first object from being changed through that pointer.


But not on char *const ptr_ch2.

new.c contains the errors that you're looking for:

/* BEGIN new.c */

#include <stdio.h>

int main ()
{
char ch1= 'Y';
char ch2='O';
const char *ptr_ch1 = &ch1;
char *const ptr_ch2 = &ch2;

printf ("\n ptr_ch1 -> %c \n", *ptr_ch1);
*ptr_ch1 = 'G';
printf ("\n Modified ptr_ch1 -> %c \n", *ptr_ch1);
++ptr_ch2;
return 0;

}

/* END new.c */

Got it. Thanks Pete. Thanks Thomas.
 
C

CBFalconer

I am new to the C language. Got the doubt which is discussed
frequently. I have the following piece of code which is compiled
without warnings and run Successfully.

Issue 1 : I can change the value pointed by const char *ptr_ch1;
Issue 2: I can change the Pointer location on char const *ptr_ch2.

Those two generate the same code, where the const item is the char
pointed to. If you want to control the const (ness) of the
pointer, use:

char * const ptr3 = &something;

note that such an item MUST be initialized in the declaration.
 
T

Tomás Ó hÉilidhe

        char * const ptr3;
        unsigned char uc [sizeof ptr3];
        int count;

        memcpy(uc, &ptr3, sizeof ptr3);
The behavior is implementation-defined, but not undefined.


The compiler manual doesn't need to say how it treats uninitialised
memory, so I'd say "unspecified" instead of "implementation-defined".
 
J

James Kuyper

CBFalconer said:
Those two generate the same code, where the const item is the char
pointed to. If you want to control the const (ness) of the
pointer, use:

char * const ptr3 = &something;

note that such an item MUST be initialized in the declaration.

While the C++ standard imposes such a requirement, the C standard does not.
=======================================================================
#include <stdlib.h>
char * const ptra; // Tentative definition
char * const ptrb; // Another one.

int main(void)
{
static char *const ptrc; // Static, zero-initialized by default.
char * const ptrd; // Uninitialized

return ptrb == 0 && ptrc == 0 && ptra == (char*)&ptrb
? EXIT_SUCCESS : EXIT_FAILURE;
}

char * const ptra = (char*)&ptrb; // Actual definition

// Because this is the end of the translation unit, and there's still no
// external definition for ptrb, so the standard mandates that the
// compiler behaves as though the following external definition had been
// given:

// char * const ptrb = 0;
=======================================================================

Note that ptrd is useless; it has an indeterminate value, which might be
a trap representation, and cannot be given a determinate value by any
code with defined behavior. There's no safe way to make any use of it.

Both ptrb and ptrc are functional equivalents of (char*)0, except that
they don't qualify as constant expressions, which makes them pretty
pointless.

However, despite the fact that this code contains 4 declarations of
const objects without any explicit initializers, this is still strictly
conforming code: there's no syntax errors, constraint violations, or
undefined behavior, and the observable behavior of the program does not
depend in any way upon implementation-defined or otherwise unspecified
behavior.
 

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

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top