Is C++ a type-safe language ??

N

Nitin Bhardwaj

Hi all,

It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C). So how does one explain the following behaviour :

int main(void)
{
char *p = NULL;
p = "A String Literal";//the compiler isuues no error/warning here
// but ideally it should...as p is a non-const
// pointer and the string literal has the type
// const char *
// So, a conversion from const-ptr TO non-const
// should elicite warning/error from the compiler !!

return 0;
}

I've tried it on both MSVC++ 6 compiler on Windows 2000 ( Intel P IV )
and GNU C++ compiler gcc 3.x RedHat GNU\Linux ( Intel P IV )

Thanks in advance.
 
J

John Harrison

Hi all,

It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C). So how does one explain the following behaviour :

int main(void)
{
char *p = NULL;
p = "A String Literal";//the compiler isuues no error/warning here
// but ideally it should...as p is a non-const
// pointer and the string literal has the type
// const char *
// So, a conversion from const-ptr TO non-const
// should elicite warning/error from the compiler !!

return 0;
}

I've tried it on both MSVC++ 6 compiler on Windows 2000 ( Intel P IV )
and GNU C++ compiler gcc 3.x RedHat GNU\Linux ( Intel P IV )

Thanks in advance.

It's clearly non-type safe but is done for backward compatibility. When C
was invented there was no const and when C introduced const it was felt
that too much existing code would break if the above was forbidden.
C++ has retained this.

john
 
R

Rufus V. Smith

Nitin Bhardwaj said:
Hi all,

It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C). So how does one explain the following behaviour :

int main(void)
{
char *p = NULL;
p = "A String Literal";//the compiler isuues no error/warning here
// but ideally it should...as p is a non-const
// pointer and the string literal has the type
// const char *
// So, a conversion from const-ptr TO non-const
// should elicite warning/error from the compiler !!

return 0;
}

I've tried it on both MSVC++ 6 compiler on Windows 2000 ( Intel P IV )
and GNU C++ compiler gcc 3.x RedHat GNU\Linux ( Intel P IV )

const-ness is definitely one of the thornier issues in type safety.

next question?

Rufus
 
A

Alf P. Steinbach

* Nitin Bhardwaj:
It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C).

That is incorrect.

However, C++ supports type-safety in more ways than C.

So it's possible to program in C++ in (more or less) type-safe ways.


So how does one explain the following behaviour :

int main(void)
{
char *p = NULL;
p = "A String Literal";//the compiler isuues no error/warning here
// but ideally it should...as p is a non-const
// pointer and the string literal has the type
// const char *
// So, a conversion from const-ptr TO non-const
// should elicite warning/error from the compiler !!

return 0;
}

I've tried it on both MSVC++ 6 compiler on Windows 2000 ( Intel P IV )
and GNU C++ compiler gcc 3.x RedHat GNU\Linux ( Intel P IV )

It's backward compatibility with C.

There are other far more horrendous compatibility-derived issues.

For instance, automatic conversion of array type to pointer type and
treating pointers as arrays, in the context of an array of objects.

On the other hand, in some respects C++ is more type-safe than e.g.
Java.

For example, template support enables static type-checking in many
situations where it's not possible in (old non-generic) Java; C++ har
more stringent type-checking (although not 100%) at link time; C++
constructors enforce class invariants while Java constructors do not.
 
J

jeffc

Nitin Bhardwaj said:
Hi all,

It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C). So how does one explain the following behaviour :

I would say "strongly typed" is not exactly the same thing as "type-safe".
"strong" is a relative word, is it not?
 
S

SaltPeter

Nitin Bhardwaj said:
Hi all,

It is said that C++ is a strongly typed language and thus a type-safe
language (unlike C). So how does one explain the following behaviour :

int main(void)
{
char *p = NULL;
p = "A String Literal";//the compiler isuues no error/warning here
// but ideally it should...as p is a non-const
// pointer and the string literal has the type
// const char *
// So, a conversion from const-ptr TO non-const
// should elicite warning/error from the compiler !!

Ideally, what your compiler should do is generate an error about NULL
not being defined.

So you are suggesting that this should be illegal as well?
int n = 5;

Or are you suggesting that a literal 5 should also be treated as an
lvalue?

Try compiling with the commented line:

#include <iostream>
#include <stdio.h>

// main.cpp

int main()
{
const char *p = NULL;
p = "an rvalue";

//char *pc = p; // fails
const char *pc = p;

std::cout << " pc is not " << pc << std::endl;

return 0;
}
 
N

Nitin Bhardwaj

SaltPeter said:
Ideally, what your compiler should do is generate an error about NULL
not being defined.

I had provided a code snippet & not the whole program :) , Inclusion
of standard header(s) was assumed.
So you are suggesting that this should be illegal as well?
int n = 5;

Or are you suggesting that a literal 5 should also be treated as an
lvalue?

Try compiling with the commented line:

#include <iostream>
#include <stdio.h>


You do not need to seperately #include <stdio.h> to have NULL defined,
// main.cpp

int main()
{
const char *p = NULL;
p = "an rvalue";

//char *pc = p; // fails

Thats what I was pointing out: Here the expression fails because the
type of 'p' is const char * and 'pc' is char *....so the compiler
gives 'cannot convert from const char * to char *'. But why doesn't
give in the following case ?

char *str = "String Literal";

Here also type of "String Literal" is const char * and type of str is
char * !!
 
S

Sam Holden

Thats what I was pointing out: Here the expression fails because the
type of 'p' is const char * and 'pc' is char *....so the compiler
gives 'cannot convert from const char * to char *'. But why doesn't
give in the following case ?

char *str = "String Literal";

Here also type of "String Literal" is const char * and type of str is
char * !!

It's a special case, in order to make C programmers happy. The ancient
standard draft I have available lists it as deprecated but I don't know
if that stuck - someone else certainly will though.
 
J

John Harrison

Thats what I was pointing out: Here the expression fails because the
type of 'p' is const char * and 'pc' is char *....so the compiler
gives 'cannot convert from const char * to char *'. But why doesn't
give in the following case ?

char *str = "String Literal";

Here also type of "String Literal" is const char * and type of str is
char * !!

No it isn't, the type of "String Literal" is const char [15], it's an
array not a pointer.

The conversion of this array or const char to char* is explicitly allowed
by 4.2 paragraph 2 of the standard. It's purpose is compatibility with C.
In the very old days C did not have const and so code like your example
was commonplace.

Nevertheless it is an error to use this to modify a string literal.

One excemption from type safety rules for the purpose of bacwards
compatibility does not make C++ a non-type safe language. It is still more
type safe than any other language in common use (AFAIK).

john
 
S

SaltPeter

Nitin Bhardwaj said:
"SaltPeter" <[email protected]> wrote in message

I had provided a code snippet & not the whole program :) , Inclusion
of standard header(s) was assumed.

No, its not assumed. Your case is the perfect example why. iostream.h is
deprecated and should not be included in any modern code. Basicly, without
including the headers, NULL could be anything. Surely, you aren't expecting
folks to rely on a crystal ball to substitute values for undefined
constants.
You do not need to seperately #include <stdio.h> to have NULL defined,
<iostream.h> is enough for that !!

iostream.h is not part of the C++ standard anymore.
#include <iostream>

And as Benny Hill use to say...
When you ASSUME, you make an ASS out of U and ME, lol.
Thats what I was pointing out: Here the expression fails because the
type of 'p' is const char * and 'pc' is char *....so the compiler
gives 'cannot convert from const char * to char *'. But why doesn't
give in the following case ?

char *str = "String Literal";

Here also type of "String Literal" is const char * and type of str is
char * !!

How do you figure that an array of chars all of a sudden denotes a pointer
to char? I'm baffled. I can see the str pointer(the lvalue), but how do you
magicly deduce that the string literal, in this case: an array of
characters, has become a pointer, or a constant pointer? Its just an array
of characters, thats it.
 
R

Richard Herring

SaltPeter said:
No, its not assumed. Your case is the perfect example why. iostream.h is
deprecated and should not be included in any modern code. Basicly, without
including the headers, NULL could be anything. Surely, you aren't expecting
folks to rely on a crystal ball to substitute values for undefined
constants.

Oh, come off it. NULL is cited all over the place in the Standard, and
defined in *seven* different standard headers, any of which could be
included by any of the others. You would have to be out of your mind to
define it as anything else.
 
B

Bill Seurer

Richard said:
NULL is cited all over the place in the Standard

Actually it isn't. I just searched on an older PDF copy of the standard
and there were about 20 mentions all of which were in the descriptions
of the C headers that define NULL or in some discussions of them in the
appendices.
 
R

Richard Herring

Bill Seurer said:
Actually it isn't.

It doesn't appear on every line of every page, I'll grant you.
I just searched on an older PDF copy of the standard and there were
about 20 mentions all of which were in the descriptions of the C
headers that define NULL

And all those headers are part of the C++ standard.
or in some discussions of them in the appendices.

And in the discussion of streambufs. That's not a C feature.

Be that as it may, my point stands. If you include _any_ standard
header, you can no longer safely assume that NULL is not defined.
 
S

SaltPeter

Richard Herring said:
Oh, come off it. NULL is cited all over the place in the Standard, and
defined in *seven* different standard headers, any of which could be
included by any of the others. You would have to be out of your mind to
define it as anything else.

Wrong, both by fact and principle. The issue is not over where NULL is
defined but rather if NULL is defined. Read the OP's original quest. His
code ignores the include directives used in his program. Therefore:

int main()
{
char *p = NULL
// ....
}

can't be compiled. Code posted in the newsgroup should specify the headers
included.

I strongly disagree with your point of view and the OP's point of view that
included headers should be assumed. All of which is rather relevent since it
turns out he was using iostream.h rather than iostream. That was the whole
point of the NULL issue.
 
R

Richard Herring

SaltPeter said:
Wrong, both by fact and principle.

Sounds grand, but on deeper analysis means little. Which fact above is
wrong? Which principle?
The issue is not over where NULL is
defined

No. The issue is the type of a string literal, and why the standard
allows conversion of const pointer to non-const pointer in those
circumstances. Your nitpicking over NULL is a digression from the real
point.
but rather if NULL is defined.

.... but if you insist on such nitpicking, the issue is not _if_ NULL is
defined, but _how_ it might be defined, and consequently whether one can
deduce the OP's intention.
Read the OP's original quest. His
code ignores the include directives used in his program. Therefore:

int main()
{
char *p = NULL

If that had merely been
char * p;
the OP's original question would have been substantively identical, and
the answer the same. NULL is an irrelevancet.
// ....
}

can't be compiled. Code posted in the newsgroup should specify the headers
included.

I strongly disagree with your point of view

Then you misunderstand it. My point is not that included headers should
be assumed, but that the absence of anything that might be defined - per
the standard - in included standard headers must not be assumed. It's in
the same category as things like defining identifiers with leading
underscores.
and the OP's point of view that
included headers should be assumed.

All of which is rather relevent since it
turns out he was using iostream.h rather than iostream.

Hardly. Whichever standard headers he included, there would only be two
possible outcomes:
(a) NULL is undefined
(b) NULL is defined as a null pointer constant.
(c) There is no (c)
Therefore no crystal ball is required to deduce what the OP must have
meant by NULL.
 
S

SaltPeter

Richard Herring said:
Sounds grand, but on deeper analysis means little. Which fact above is
wrong? Which principle?

NULL isn't defined in the standard, although rather heavily used and
implied. Example: iterating to past-the-end in an STL container.
No. The issue is the type of a string literal, and why the standard
allows conversion of const pointer to non-const pointer in those
circumstances. Your nitpicking over NULL is a digression from the real
point.

A literal string is NOT a pointer. You are referring to a rule that doesn't
apply here. Its an array of const characters which in the OP's case was used
to initialize a pointer. There is a fine line one needs to walk when one
starts saying statements like: "a temporary integer variable therefore
implies a pointer-to-int". Its does not.
... but if you insist on such nitpicking, the issue is not _if_ NULL is
defined, but _how_ it might be defined, and consequently whether one can
deduce the OP's intention.


If that had merely been
char * p;
the OP's original question would have been substantively identical, and
the answer the same. NULL is an irrelevancet.

NULL, like any constant is relevent. Here, try to compile this:

#include <iostream>

#define NULL ((void *)0)

int()
{
int *p = NULL
std::cout << p;
}

Note the NULL definition using C's definition (does not compile, not allowed
in C++ to initialize a pointer). This solves the issue of why NULL can't and
must not be "assumed".
Then you misunderstand it. My point is not that included headers should
be assumed, but that the absence of anything that might be defined - per
the standard - in included standard headers must not be assumed. It's in
the same category as things like defining identifiers with leading
underscores.


Hardly. Whichever standard headers he included, there would only be two
possible outcomes:
(a) NULL is undefined
(b) NULL is defined as a null pointer constant.
(c) There is no (c)
Therefore no crystal ball is required to deduce what the OP must have
meant by NULL.

c) explained above. ((void *)0) is illegal in C++.
 
O

Old Wolf

SaltPeter said:
No, its not assumed. Your case is the perfect example why. iostream.h is
deprecated and should not be included in any modern code.

iostream.h was never in any standard. Therefore it cannot be
deprecated.
 
V

Victor Bazarov

SaltPeter said:
Thats not correct, the old header was deprecated by the ISO/ANSI C++
committee.
http://www.parashift.com/c++-faq-lite/coding-standards.html

I think you're confused about what is deprecated. Read that FAQ chapter
carefully. C headers that have the .h form are deprecated. C++ headers
have never had standard form with .h, so they simply cannot be deprecated.
Deprecated means "OK in this edition of the Standard, but may not be OK
later, so don't rely on them".

Better yet, get yourself a copy of the Standard. You will see no mention
of <iostream.h> in it.

V
 

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,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top