|
From: Abhijit S. <mu...@gm...> - 2002-06-14 17:13:55
|
I was just going through the sources of the class libraries in Turbo C++
version 3.0, and found this code. How does the program modify aPtr even
though it says it's a const?
-------CLASSLIB/SOURCE/STRNG.CPP------
String::String( const char *aPtr )
{
if ( aPtr == 0 )
aPtr = "";
len = strlen( aPtr ) + 1;
theString = new char[ len ];
CHECK( theString != 0 );
strcpy( theString, aPtr );
}
--------------------------------------
After seeing this, I tried compiling the following file in MingW, and it did
(with -Wall, no warnings)
--------------------------------------
void do_stuff(const char *buf)
{
if(!buf)
buf = "";
}
int main()
{
do_stuff(0);
return 0;
}
--------------------------------------
How? Doesn't
buf = "";
translate to assign "" to buf?
--------------------------
http://mudeth.tripod.com
|
|
From: Mac R. <re...@no...> - 2002-06-14 18:51:56
|
const and pointers gets tricky, because there are TWO things that could be
constant : the pointer itself, or the data that the pointer is pointing at.
In the code you found (const char * aPtr), the const refers to the data
that the pointer is pointing at. If, inside that function, you attempted
to say something like:
aPtr[0] = '\0';
The compiler should refuse it. Since technically the pointer is only
pointing at the first character, it would not *HAVE* to refuse
modifications to aPtr[1] or any later character, but I believe the C++
standard makes some special cases to handle arrays of chars because they
are so prevalent.
You can also have "char const * anotherPtr", which (if I haven't screwed
this up) is a constant pointer to non-constant data. That would mean that:
anotherPtr[0] = '\0';
would be legal, but:
anotherPtr = "";
would not.
Lastly, if you REALLY want everything to be constant, you can declare:
const char const * lockedPtrToLockedData = "Hello World";
Nothing about that can be modified without silly casting tricks.
To keep all this straight, try reading the declaration right-to-left:
const char * aPtr == (const char) (*) (aPtr)
"aPtr is a pointer to constant characters"
char const * bPtr == (char) (const *) (bPtr)
"bPtr is a constant pointer to characters"
const char const * cPtr == (const char) (const *) (cPtr)
"cPtr is a constant pointer to constant characters"
The really unfortunate thing about this is that you have to read the
declaration right to left, but when you see "const" you have to associate
it with the thing to its right. That always makes me feel like I'm having
to flip between reading right-to-left and reading left-to-right.
That ends the useful help section of this posting. Now for the whiny "I
wish they'd done it differently part":
I really wish that C had used the Pascal or (modern) BASIC declaration style:
Pascal:
MyInteger : INTEGER;
BASIC:
Dim MyInteger As Integer
These declarations are read left to right, and can easily be extended for
consts and pointers. Wouldn't the following have been easier to read?
aPtr : * const char; // pointer to constant char
bPtr : const * char; // constant pointer to char
cPtr : const * const char; // constant pointer to constant char
or, while I'm dreaming up changes that will never happen -- it has always
bothered me that "char *" was a pointer, but to get a pointer from a
variable, you used "&variable". From that standpoint, I would prefer &
instead of * for declaration, resulting in:
aPtr : & const char;
etc.
(Of course, you'd have to come up with a different character for references
in C++) I also think that @ would be a better dereferencing operator than
*, because you are trying to access the value "at" an address. But it's
far too late for these things now, so they will just remain in my wishful
thinking category...
Mac
At 10:42 PM 6/14/02 +0530, Abhijit Shylanath wrote:
>I was just going through the sources of the class libraries in Turbo C++
>version 3.0, and found this code. How does the program modify aPtr even
>though it says it's a const?
>
>-------CLASSLIB/SOURCE/STRNG.CPP------
>String::String( const char *aPtr )
>{
> if ( aPtr == 0 )
> aPtr = "";
>
> len = strlen( aPtr ) + 1;
> theString = new char[ len ];
> CHECK( theString != 0 );
> strcpy( theString, aPtr );
>}
-
_____________________________ /"\
Mac Reiter \ / ASCII Ribbon Campaign
Nomadics, Inc. X Against HTML Mail
re...@no... / \ (To join the campaign, simply use
this in your signature.)
|
|
From: Juliano <jp...@bo...> - 2002-06-14 19:11:08
|
I'm sorry if I'm wrong, but... Isn't "const char *y" a way to say that the address value stored in the pointer "y" can't be changed? In other words, I can change the value pointed by the address stored in "y", but I can't change the address stored in "y" itself. Isn't it the way pointers work? Am I doing something wrong? []s Juliano -----Original Message----- From: dev...@li... [mailto:dev...@li...] On Behalf Of Mac Reiter Sent: sexta-feira, 14 de junho de 2002 15:50 To: Dev-C++ Mailing List Subject: Re: [Dev-C++] const modifier? Quer ter seu pr=F3prio endere=E7o na Internet? Garanta j=E1 o seu e ainda ganhe cinco e-mails personalizados. = Dom=EDniosBOL - http://dominios.bol.com.br const and pointers gets tricky, because there are TWO things that could be constant : the pointer itself, or the data that the pointer is pointing at. In the code you found (const char * aPtr), the const refers to the data that the pointer is pointing at. If, inside that function, you attempted to say something like: aPtr[0] =3D '\0'; The compiler should refuse it. Since technically the pointer is only pointing at the first character, it would not *HAVE* to refuse modifications to aPtr[1] or any later character, but I believe the C++ standard makes some special cases to handle arrays of chars because they are so prevalent. You can also have "char const * anotherPtr", which (if I haven't screwed this up) is a constant pointer to non-constant data. That would mean that: anotherPtr[0] =3D '\0'; would be legal, but: anotherPtr =3D ""; would not. Lastly, if you REALLY want everything to be constant, you can declare: const char const * lockedPtrToLockedData =3D "Hello World"; Nothing about that can be modified without silly casting tricks. To keep all this straight, try reading the declaration right-to-left: const char * aPtr =3D=3D (const char) (*) (aPtr) "aPtr is a pointer to constant characters" char const * bPtr =3D=3D (char) (const *) (bPtr) "bPtr is a constant pointer to characters" const char const * cPtr =3D=3D (const char) (const *) (cPtr) "cPtr is a constant pointer to constant characters" The really unfortunate thing about this is that you have to read the declaration right to left, but when you see "const" you have to associate it with the thing to its right. That always makes me feel like I'm having to flip between reading right-to-left and reading left-to-right. That ends the useful help section of this posting. Now for the whiny "I wish they'd done it differently part": I really wish that C had used the Pascal or (modern) BASIC declaration style: Pascal: MyInteger : INTEGER; BASIC: Dim MyInteger As Integer These declarations are read left to right, and can easily be extended for consts and pointers. Wouldn't the following have been easier to read? aPtr : * const char; // pointer to constant char bPtr : const * char; // constant pointer to char cPtr : const * const char; // constant pointer to constant char or, while I'm dreaming up changes that will never happen -- it has always bothered me that "char *" was a pointer, but to get a pointer from a variable, you used "&variable". From that standpoint, I would prefer & instead of * for declaration, resulting in: aPtr : & const char; etc. (Of course, you'd have to come up with a different character for references in C++) I also think that @ would be a better dereferencing operator than *, because you are trying to access the value "at" an address. But it's far too late for these things now, so they will just remain in my wishful thinking category... Mac At 10:42 PM 6/14/02 +0530, Abhijit Shylanath wrote: >I was just going through the sources of the class libraries in Turbo=20 >C++ version 3.0, and found this code. How does the program modify aPtr=20 >even though it says it's a const? > >-------CLASSLIB/SOURCE/STRNG.CPP------ >String::String( const char *aPtr ) >{ > if ( aPtr =3D=3D 0 ) > aPtr =3D ""; > > len =3D strlen( aPtr ) + 1; > theString =3D new char[ len ]; > CHECK( theString !=3D 0 ); > strcpy( theString, aPtr ); >} - _____________________________ /"\ Mac Reiter \ / ASCII Ribbon Campaign Nomadics, Inc. X Against HTML Mail re...@no... / \ (To join the campaign, simply use this in your signature.) =20 _______________________________________________________________ Don't miss the 2002 Sprint PCS Application Developer's Conference August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source=3Dosdntextlink _______________________________________________ Dev-cpp-users mailing list Dev...@li... https://lists.sourceforge.net/lists/listinfo/dev-cpp-users |
|
From: Mac R. <re...@no...> - 2002-06-14 19:57:09
|
I must apologize for _part_ of my preceding post, and should remember to
always run programs to make sure I'm not off slightly. I was still right
about the particular case raised by Juliano:
const char *y ==> (const char) (*) y ==> y is mutable pointer to const char
(mutable just means non-const) This means that "const char *y" will allow
you to change *where* y points, but will not allow you to change the data
that y is pointing at.
If you read my previous post, you would think that what you want is:
(WARNING : the following decomposition is incorrect!)
char const *y ==> (char) (const *) y ==> y is const pointer to mutable char
However, this is *WRONG*. "char const *y" is functionally identical to
"const char *y". (I really hate this syntax...) I discovered this while
writing a test program. To make the pointer constant, but the characters
mutable, you need:
char * const y ==> (char *) (const y) ==> y is a const pointer to mutable char
(I hate this syntax. I hate this syntax. I hate this syntax.)
Apparently C++ parses these two declarations identically:
const char *y ==> (const char *) (y)
char const *y ==> (char const *) (y)
-------------------------------------------------------------------------
THE MORAL OF THE STORY:
Split pointer declarations at the '*'. Then you can tell where the
const will be applied.
const char * y ==> (const char) * (y) ==> chars are const, y is mutable
char const * y ==> (char const) * (y) ==> chars are const, y is mutable
char * const y ==> (char) * (const y) ==> chars are mutable, y is const
const char * const y ==> (const char) * (const y) ==>
chars are const, y is const
const char const * const y ==> (const char const) * (const y) ==>
warning: const specifier used twice
-------------------------------------------------------------------------
Here is the test code -- put it in a file and compile it. The compiler
will throw an error on the two lines where a constant value is being
changed (or trying to be changed...)
int main(int argc, char **argv)
{
char buffer1[] = "Hello";
char buffer2[] = "World";
// This declares a mutable pointer that points to constant data
const char * a = &(buffer1[0]);
// This declares a constant pointer that points to mutable data
char * const b = &(buffer1[0]);
a[1] = 'u'; // illegal, because "mutable a" points to "const char"
b[1] = 'u'; // OK, because "const b" is a mutable "char *"
a = &(buffer2[0]); // OK, because "mutable a" can change
b = &(buffer2[0]); // illegal, because "const b" cannot change
}
Anybody care to join me in my mantra?
I HATE THIS SYNTAX!
I Hate This Syntax!
i hate this syntax
...
..
.
Mac
At 04:10 PM 6/14/02 -0300, Juliano wrote:
> I'm sorry if I'm wrong, but... Isn't "const char *y" a way to
>say that the address value stored in the pointer "y" can't be changed?
>In other words, I can change the value pointed by the address stored in
>"y", but I can't change the address stored in "y" itself.
>
> Isn't it the way pointers work? Am I doing something wrong?
>
> []s
> Juliano
[My previous post clipped out because it contained incorrect information,
which I choose not to propagate any further... Mac]
-
_____________________________ /"\
Mac Reiter \ / ASCII Ribbon Campaign
Nomadics, Inc. X Against HTML Mail
re...@no... / \ (To join the campaign, simply use
this in your signature.)
|
|
From: Juliano <jp...@bo...> - 2002-06-14 20:35:49
|
Oh God... :). I think its clear now... At least for me. Thank you. Juliano -----Original Message----- From: dev...@li... [mailto:dev...@li...] On Behalf Of Mac Reiter Sent: sexta-feira, 14 de junho de 2002 16:55 To: 'Dev-C++ Mailing List' Subject: RE: [Dev-C++] const modifier? Quer ter seu pr=F3prio endere=E7o na Internet? Garanta j=E1 o seu e ainda ganhe cinco e-mails personalizados. = Dom=EDniosBOL - http://dominios.bol.com.br I must apologize for _part_ of my preceding post, and should remember to always run programs to make sure I'm not off slightly. I was still right about the particular case raised by Juliano: const char *y =3D=3D> (const char) (*) y =3D=3D> y is mutable pointer = to const char (mutable just means non-const) This means that "const char *y" will allow you to change *where* y points, but will not allow you to change the data that y is pointing at. If you read my previous post, you would think that what you want is: (WARNING : the following decomposition is incorrect!) char const *y =3D=3D> (char) (const *) y =3D=3D> y is const pointer to = mutable char However, this is *WRONG*. "char const *y" is functionally identical to "const char *y". (I really hate this syntax...) I discovered this while writing a test program. To make the pointer constant, but the characters mutable, you need: char * const y =3D=3D> (char *) (const y) =3D=3D> y is a const pointer = to mutable char (I hate this syntax. I hate this syntax. I hate this syntax.) Apparently C++ parses these two declarations identically: const char *y =3D=3D> (const char *) (y) char const *y =3D=3D> (char const *) (y) ------------------------------------------------------------------------ - THE MORAL OF THE STORY: Split pointer declarations at the '*'. Then you can tell where the const will be applied. const char * y =3D=3D> (const char) * (y) =3D=3D> chars are const, y is = mutable char const * y =3D=3D> (char const) * (y) =3D=3D> chars are const, y is = mutable char * const y =3D=3D> (char) * (const y) =3D=3D> chars are mutable, y = is const const char * const y =3D=3D> (const char) * (const y) =3D=3D> chars are const, y is const const char const * const y =3D=3D> (const char const) * (const y) = =3D=3D> warning: const specifier used twice ------------------------------------------------------------------------ - Here is the test code -- put it in a file and compile it. The compiler will throw an error on the two lines where a constant value is being changed (or trying to be changed...) int main(int argc, char **argv) { char buffer1[] =3D "Hello"; char buffer2[] =3D "World"; // This declares a mutable pointer that points to constant data const char * a =3D &(buffer1[0]); // This declares a constant pointer that points to mutable data char * const b =3D &(buffer1[0]); a[1] =3D 'u'; // illegal, because "mutable a" points to "const char" b[1] =3D 'u'; // OK, because "const b" is a mutable "char *" a =3D &(buffer2[0]); // OK, because "mutable a" can change b =3D &(buffer2[0]); // illegal, because "const b" cannot change = } Anybody care to join me in my mantra? I HATE THIS SYNTAX! I Hate This Syntax! i hate this syntax ... .. . Mac At 04:10 PM 6/14/02 -0300, Juliano wrote: > I'm sorry if I'm wrong, but... Isn't "const char *y" a way to say that=20 >the address value stored in the pointer "y" can't be changed? In other=20 >words, I can change the value pointed by the address stored in "y", but >I can't change the address stored in "y" itself. > > Isn't it the way pointers work? Am I doing something wrong? > > []s > Juliano [My previous post clipped out because it contained incorrect information, which I choose not to propagate any further... Mac] - _____________________________ /"\ Mac Reiter \ / ASCII Ribbon Campaign Nomadics, Inc. X Against HTML Mail re...@no... / \ (To join the campaign, simply use this in your signature.) =20 _______________________________________________________________ Don't miss the 2002 Sprint PCS Application Developer's Conference August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source=3Dosdntextlink _______________________________________________ Dev-cpp-users mailing list Dev...@li... https://lists.sourceforge.net/lists/listinfo/dev-cpp-users |
|
From: Abhijit S. <mu...@gm...> - 2002-06-15 02:59:31
|
Thanks for that... BTW, I hate this SYNTAX, I hate this Syntax, I hate this syntax. Was that all right? :) -------------------------- http://mudeth.tripod.com ----- Original Message ----- From: "Mac Reiter" <re...@no...> To: "'Dev-C++ Mailing List'" <dev...@li...> Sent: Saturday, June 15, 2002 1:25 AM Subject: RE: [Dev-C++] const modifier? > Anybody care to join me in my mantra? > > I HATE THIS SYNTAX! > I Hate This Syntax! > i hate this syntax |
|
From: Ioannis V. <no...@ho...> - 2002-06-15 03:17:59
|
> -----Original Message----- > From: dev...@li... > [mailto:dev...@li...] On Behalf > Of Mac Reiter > Sent: Friday, June 14, 2002 9:50 PM > To: Dev-C++ Mailing List > Subject: Re: [Dev-C++] const modifier? > > The compiler should refuse it. Since technically the pointer is only > pointing at the first character, it would not *HAVE* to refuse > modifications to aPtr[1] or any later character, but I believe the C++ > standard makes some special cases to handle arrays of chars > because they > are so prevalent. No, it has to refuse in C too. It remains a const char * in all cases. > > You can also have "char const * anotherPtr", which (if I > haven't screwed > this up) is a constant pointer to non-constant data. That > would mean that: > char const *p is the same as const char *p. You meant char * const p. > I really wish that C had used the Pascal or (modern) BASIC > declaration style: > > Pascal: > MyInteger : INTEGER; > > BASIC: > Dim MyInteger As Integer Thank God it doesn't. :) > or, while I'm dreaming up changes that will never happen -- > it has always > bothered me that "char *" was a pointer, but to get a pointer from a > variable, you used "&variable". From that standpoint, I > would prefer & > instead of * for declaration, resulting in: > > aPtr : & const char; > etc. It could happen but we would still need * since we would confuse the dereference operator with the address of operator, which are different things. > > (Of course, you'd have to come up with a different character > for references > in C++) I also think that @ would be a better dereferencing > operator than > *, because you are trying to access the value "at" an > address. But it's > far too late for these things now, so they will just remain > in my wishful > thinking category... Well yes, these are details. The main idea here is that the C/C++ languages get the job done. One could like more @, another could like more * and i think it is not possible all people to reach an agreement on what symbols to be used. Personally i like things as they are. Ioannis * Ioannis Vranos * Programming pages: http://www.noicys.cjb.net * Alternative URL: http://run.to/noicys |
|
From: Ioannis V. <no...@ho...> - 2002-06-15 03:06:54
|
> -----Original Message-----
> From: dev...@li...
> [mailto:dev...@li...] On Behalf
> Of Abhijit Shylanath
> Sent: Friday, June 14, 2002 8:13 PM
> To: Dev-C++ Mailing List
> Subject: [Dev-C++] const modifier?
>
>
> I was just going through the sources of the class libraries
> in Turbo C++
> version 3.0, and found this code. How does the program modify
> aPtr even
> though it says it's a const?
const char *p means that it can not change the contents of the object
where it points. Example:
const char *p="constast string 1";
p="constant string 2";
To not be able to point to somewhere else:
// constant pointer
char * const p=some_char_array;
const char *const p="something";
p cannot point to somewhere else and cannot changge the object where it
points. For example:
cout<<p[2]; // valid
p[2]='7'; // invalid
p="something else"; //invalid
for(int i=0; i<18; i++)
cout<<"did you know that?"[i]; // valid
>
> -------CLASSLIB/SOURCE/STRNG.CPP------
> String::String( const char *aPtr )
> {
> if ( aPtr == 0 )
> aPtr = "";
>
> len = strlen( aPtr ) + 1;
> theString = new char[ len ];
> CHECK( theString != 0 );
> strcpy( theString, aPtr );
> }
> --------------------------------------
>
> After seeing this, I tried compiling the following file in
> MingW, and it did
> (with -Wall, no warnings)
>
> --------------------------------------
> void do_stuff(const char *buf)
> {
> if(!buf)
> buf = "";
> }
>
> int main()
> {
> do_stuff(0);
> return 0;
> }
> --------------------------------------
>
> How? Doesn't
> buf = "";
> translate to assign "" to buf?
A literal behaves like an array of chars. An array behaves like a
pointer to its first element. The first element here is '\0' (which is
always 0). I did not understand the last question btw.
Since you learn C++ i recommend you leave the low level stuff for
later, and learn to deal C++ as a high level language, and not as C.
Ioannis
* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys
|