By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,694 Members | 1,845 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,694 IT Pros & Developers. It's quick & easy.

Why compiler not generating any warning ?

P: n/a
Consider the following piece of code:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
}

On compiling this program: cc -c99 -check -portable test.c
I don't get any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.

Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
But on compilation I don't get any warning message.
So, what is the way to cacth these type of bugs ? Is there
any other tool that may find out all undefined, unportable
behaviour ?
I tried *lint* as well but it also didn't warned for this.

Only, the typecasting to "char *" should be allowed which is
*guaranteed* to point to the lowest addressed byte of the structure.

Nov 14 '05 #1
Share this Question
Share on Google+
29 Replies


P: n/a
ju**********@yahoo.co.in wrote:
But on compilation I don't get any warning message.
So, what is the way to cacth these type of bugs ?


Learn more C.

--
pete
Nov 14 '05 #2

P: n/a
ju**********@yahoo.co.in wrote:
Consider the following piece of code: struct junk {
int i_val;
int i_val1;
char c_val;
}; int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
} On compiling this program: cc -c99 -check -portable test.c
I don't get any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me. Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
You will also get undefined behaviour when you write past the end of
an array, if you use a pointer to already deallocated memory etc. ect.
but the compiler won't warn about that.
But on compilation I don't get any warning message.
Well, you tell the compiler "convert this pointer to a pointer of
a different type". So the compiler does, and since you explicitely
told it to do that why should it doubt the wisdom of your commands?
If you cast you basically say "I know what I am doing, don't tell
me I shouldn't, if I would like you to warn me I wouldn't use that
[expletive censored] cast". And afterwards you tell it "assign to
a pointer from a pointer of the same type" which is 100% legal and
not dangerous at all.
So, what is the way to cacth these type of bugs ? Is there
any other tool that may find out all undefined, unportable
behaviour ?
The best tool is probably between your ears;-) View all casts as
being suspicious until you're satisifed that they are ok. Finding
all instances of undefined behaviour would be impossible, it might
only happen at runtime - the compiler can't typically know in ad-
vance if e.g. in an access of an array element the index is going
to be within the bounds of the array. And undefined behaviour is
not something evil in itself, it's just something the C standard
does not define. And in most programs you actually rely on unde-
fined behaviour to work out fine, e.g. when you call a function
in a third-party library - while a strictly conforming program may
use only those features of the language and library specified in
the C standard you very often need more than just that.
Only, the typecasting to "char *" should be allowed which is
*guaranteed* to point to the lowest addressed byte of the structure.


In this case maybe yes. But there can be situations where you
know what's going to happen on the platform you're working on
(because it's well-documented) and where you have to explicitely
invoke undefined behaviour in order to get things done.

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #3

P: n/a
pete wrote:
ju**********@yahoo.co.in wrote:

But on compilation I don't get any warning message.
So, what is the way to cacth these type of bugs ?

Learn more C.

What is the point of this reply?

He is exactly trying to learn more C and asks in this
discussion group a question.

Of course *you* never asked any questions when you were learning C.

Why being rude to newcomers?

If you do not feel like answering or you think the question is silly
just do not reply.

jakob
Nov 14 '05 #4

P: n/a
jacob navia wrote:

pete wrote:
ju**********@yahoo.co.in wrote:

But on compilation I don't get any warning message.
So, what is the way to cacth these type of bugs ?

Learn more C.

What is the point of this reply?


The only way that you catch undefined behavior
that your compiler warnings miss, is by knowing enough C.
That's pretty much the whole point of reading this newsgroup.

--
pete
Nov 14 '05 #5

P: n/a

<ju**********@yahoo.co.in> wrote in message
On compiling this program: cc -c99 -check -portable test.c
I don't get any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.

Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
But on compilation I don't get any warning message.


From the switches used, I'll guess you're using the HP C compiler
on Tru64. If that's the case, you can get the compiler to
emit a diagnostic for this case.

Using -check enables most messages, but not all. To enable
all messages use the -msg_enable all option. To get the
specific message for this case, use -msg_enable ansialiascast.

Ed Vogel
HP/Compaq/DEC C/C++ Engineering
Nov 14 '05 #6

P: n/a
On Fri, 03 Jun 2005 04:03:17 -0700, junky_fellow wrote:
Consider the following piece of code:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
}

On compiling this program: cc -c99 -check -portable test.c I don't get
any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.

Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
You can safely convert a pointer to a structure to a pointer to the first
element of the structure, no undefined behavior. What is dangerous is the
pointer arithmetic you perform after the conversion. You might expect
i_ptr to point to the second member in the structure but since there may
be padding between the two integers, dereferencing the pointer would
invoke UB.
But on compilation I don't get any warning message.
I don't see anything that requires such a message.
So, what is the way to cacth these type of bugs ? Is there any other
tool that may find out all undefined, unportable behaviour ?
Nothing to add to pete and Jens responses.
I tried *lint* as well but it also didn't warned for this.
Okay.
Only, the typecasting to "char *" should be allowed which is
*guaranteed* to point to the lowest addressed byte of the structure.


Nope. In addition to this and the case I described above, a pointer to a
structure may safely be converted to a pointer to any other structure and
back again.

Robert Gamble
Nov 14 '05 #7

P: n/a
> struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */


Why? You casted pstr_junk to an integer pointer. Since you are doing
an explicit cast, the compiler assumes that you know what you are doing.
Then you told the integer pointer to advance one, which is a perfectly
valid thing for an integer pointer to do (though, because it's from the
cast, the results are undefined, but since you did an explicit cast, the
compiler won't complain). Then you assigned your new integer pointer to
i_ptr, which is of type int *.

What did you expect the compiler to complain about?

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Nov 14 '05 #8

P: n/a
On 3 Jun 2005 04:03:17 -0700, in comp.lang.c ,
ju**********@yahoo.co.in wrote:
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.
it /is/ incorrect. But you lied to the compiler, by putting in the
cast. This says "shut up, I know what I'm doing" to the compiler.
Hence no warning.
So, what is the way to cacth these type of bugs ?
Avoid casts, which are almost never needed in C, unless you're trying
to do naughty things. Or programme better...
I tried *lint* as well but it also didn't warned for this.
It can't since you already lied and told us that you knew what you
were doing....
Only, the typecasting to "char *" should be allowed which is
*guaranteed* to point to the lowest addressed byte of the structure.


You need to understand the difference between a conversion and a cast.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #9

P: n/a
On Fri, 03 Jun 2005 12:42:44 GMT, in comp.lang.c , pete
<pf*****@mindspring.com> wrote:
jacob navia wrote:

pete wrote:
> ju**********@yahoo.co.in wrote:
>
>
>>But on compilation I don't get any warning message.
>>So, what is the way to cacth these type of bugs ?
>
>
> Learn more C.
>

What is the point of this reply?


The only way that you catch undefined behavior
that your compiler warnings miss, is by knowing enough C.
That's pretty much the whole point of reading this newsgroup.


To be fair though, you could have explained *why* the compiler didn't
grumble, and why using casts is a bad idea.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #10

P: n/a
ju**********@yahoo.co.in wrote:
.... snip ... i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */


Why? You used a cast, which said specifically "I know what I am
doing and don't harass me about it". You can always add 1 to a
pointer, but the result may not be useful.

Casts are usually a sign of an error.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #11

P: n/a
CBFalconer <cb********@yahoo.com> wrote:
ju**********@yahoo.co.in wrote:
... snip ...
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */

Why? You used a cast, which said specifically "I know what I am
doing and don't harass me about it". You can always add 1 to a
pointer, but the result may not be useful. Casts are usually a sign of an error.


May I qualify this a bit? I would say that using casts in programs
that are supposed to be portable are, if not a sign of an error,
often a sign of either bad design or a sign of misunderstandings.
On the other hand, in programs - and there are a lot in the wild,
and I have to admit that I am guilty of writing my share of them
- where you deliberately invoke undefined behaviour to get things
done (e.g. in device drivers and other programs for e.g. directly
accessing hardware), casts may be the only way to go and, when used
while being aware of what they do they are not necessarily evil.
Since 'junky_fellow' seems to be on a quest of finding out where
what makes sense and what's a stupid idea I think he has some right
to get the real gray-scale picture and not just the black-and-white
view of the world;-)
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #12

P: n/a
On Fri, 03 Jun 2005 10:13:21 -0400, Jonathan Bartlett
<jo*****@eskimo.com> wrote:
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
Why? You casted pstr_junk to an integer pointer. Since you are doing
an explicit cast, the compiler assumes that you know what you are doing.
Then you told the integer pointer to advance one, which is a perfectly
valid thing for an integer pointer to do (though, because it's from the
cast, the results are undefined, but since you did an explicit cast, the


Why do you think this is undefined. After the cast, the intermediate
value must point to str_junk.i_val (which you omitted from your quoted
material). Incrementing this value by one points to the byte
immediately after this int (and still well within the struct) which is
perfectly legal as long as it is not dereferenced.
compiler won't complain). Then you assigned your new integer pointer to
i_ptr, which is of type int *.

What did you expect the compiler to complain about?

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017


<<Remove the del for email>>
Nov 14 '05 #13

P: n/a
I thank you all for your answers. From the various replies in this
thread what I concluded is that:

1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.

2) Sometimes while writing a piece of code that has to
directly access h/w (device drivers, embedded s/w) casts may be
the only option. In such cases, one must be aware of the consequences
of typecasting. Also, in such cases code review is the best
tool to find out such bugs. Compiler may not be issuing the
warning for all such *incompatible* casts.

Still I have one question. I might sound irritating but its better to
ask. Please bear with me. As most of you said that the compiler
didn't generate any warning because it was explicitly told to do
so. But there are other cases as well where explicit cast is done,
still the complier gives the warning.
eg.
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.

Nov 14 '05 #14

P: n/a
ju**********@yahoo.co.in writes:
I thank you all for your answers. From the various replies in this
thread what I concluded is that:

1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.

2) Sometimes while writing a piece of code that has to
directly access h/w (device drivers, embedded s/w) casts may be
the only option. In such cases, one must be aware of the consequences
of typecasting. Also, in such cases code review is the best
tool to find out such bugs. Compiler may not be issuing the
warning for all such *incompatible* casts.
That sounds about right.
Still I have one question. I might sound irritating but its better to
ask. Please bear with me. As most of you said that the compiler
didn't generate any warning because it was explicitly told to do
so. But there are other cases as well where explicit cast is done,
still the complier gives the warning.
eg.
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.


It might be helpful to mention what the warning says, but ...

Both the casts are no-ops; they convert a value of a given type to
that same type. If you're getting a warning about incompatible
pointer types, it has nothing to do with the casts. You'd get the
same warning without them.

But the most important point is that the assignment is illegal (though
some compilers may allow it as an extension). A cast is not an
lvalue, and cannot appear on the left side of an assignment, any more
than you can assign

x + 1 = 3;

If you invoke your compiler in conforming mode, it should reject the
assignment.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #15

P: n/a
ju**********@yahoo.co.in wrote:
1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.
Let's be a bit more pedantic and restrict that to pointer casts.
Casting "normal" values is quite common, you may often see in C89
programs e.g.

char hw[ ] = "Hello world!";
printf( "%lu\n", ( unsigned long ) strlen( hw );

to convert the size_t type return value of strlen() to something you
can print with one of the available format specifier (in C99 you bet-
ter would drop the cast and use "%zu" in the format string instead) or

double d = 42.1234;
int i = ( int ) d;

to assign the integer part of 'd' to 'i', snipping off the fractional
part.

And while casting pointers is often a sign of some trouble in a program,
there exist a few cases where they it's actually required, mostly in
conjunction with arguments of variadic functions. Take the following
(admittedly rather contrived) example program:

#include <stdio.h>
#include <stdarg.h>

double add_to( double stuff, ... )
{
va_list ap;
double *dp;

va_start( ap, stuff );
while ( ( dp = va_arg( ap, double * ) ) != NULL )
stuff += *dp;
va_end( ap );

return stuff;
}

int main( void )
{
double d0 = 1.0,
d1 = 2.0;

printf( "%f\n", add_to( 0, &d0, ( double * ) NULL ) );
printf( "%f\n", add_to( 0, &d0, &d1, ( double * ) NULL ) );
return 0;
}

The add_to() function takes a double argument plus an unspecified num-
ber of double pointers and then adds all the values the pointers are
pointing to to the first argument, returning the result. The end of
the argument list is marked by a NULL double pointer.

You may have noticed that I wrote "NULL double pointer" and not just
"NULL pointer" in the last sentence. That's because a "NULL double
pointer" could have a different bit representation than e.g. "NULL
void pointer", and it's simple values in a certain bit representation
tha get passed to functions. When you have a function foo() which is
declared as

void foo( double *dp );

and you call it like this

foo( NULL );

then the compiler knows that foo() expects a double pointer and will
convert NULL to a value with the correct bit representation for a
"NULL double pointer" and not the bit representation for e.g. a "NULL
void pointer" if the representations differ (that's another reason
why having correct function declarations can be so important).

But there's a snag with the add_to() function - the compiler doesn't
know about the types of the arguments following the first one. So
when calling add_to() the compiler can't help you by automatically
converting pointers if necessary and it's then your obligation to
make sure pointers of the correct type get passed to the function.
And that's why in the call

add_to( 0, &d0, ( double * ) NULL )

the NULL pointer actually must be cast - without the cast, the function
would be called with a value which is the bit representation of a "NULL
void pointer" and not necessarily the required representation of a "NULL
double pointer". So this is a place where a pointer cast isn't a mistake
but required. (Of course, one may argue that a design of that kind is
bad, but sometimes there may be no better solution.)
2) Sometimes while writing a piece of code that has to
directly access h/w (device drivers, embedded s/w) casts may be
the only option. In such cases, one must be aware of the consequences
of typecasting. Also, in such cases code review is the best
tool to find out such bugs. Compiler may not be issuing the
warning for all such *incompatible* casts.
The compiler probably won't issue a warning for whatever cast (except
for casts of function pointers to object pointers) since a cast tells
it that you know better - why would you use the cast otherwise?
Still I have one question. I might sound irritating but its better to
ask. Please bear with me. As most of you said that the compiler
didn't generate any warning because it was explicitly told to do
so. But there are other cases as well where explicit cast is done,
still the complier gives the warning.
eg.
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.


Something must be wrong with your compiler since this shouldn't just
generate a warning but an error message. You can't use a cast like
that on the left hand side of the assignment, it's like writing

int x;
-x = 3;

On the left hand side of an assignment you always have to have an ex-
pression that, when evaluated, must designate an object. And like "-x"
is not an existing object, so also "(int *) i_ptr" does not designate
an existing object (the result of the cast is a pointer value, not an
object). It's not like e.g.

*( (int *) i_ptr ) = 3;

where the computed value of the expression designates an object (a
memory location) a value can be assigned to (at least if 'i_ptr'
points to some memory you have permission to write to and that the
alignment requirements are satisfied).

Let's hope I got that right, otherwise someone more knowledgeable will
chime in.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #16

P: n/a
In article news:11*********************@g44g2000cwa.googlegro ups.com,
ju**********@yahoo.co.in wrote:
[...]
of typecasting. Also, in such cases code review is the best
tool to find out such bugs. Compiler may not be issuing the
warning for all such *incompatible* casts.

I've taken to creating an include file Cast.h with the following
#ifndef NO_CAST
# define CAST(x) (x)
#else
# define CAST(x)
#endif

Then I create casts as e.g.
i_ptr = CAST(int*) c_ptr;

Firstly, one can then simply find all (such) casts in your code by
searching for CAST(, which is AFAIK impossible when the cast operator is
just a type in brackets.

Also simply with #define NO_CAST, all the casts are hidden, and thus the
compiler highlights all places where casting is required. Then I can
quickly step through all the warnings to see if the casts I have in
place are valid.

I'd welcome feedback from the pro's on whether this is useful, not, or
just amazingly stupid. :-)

Since casting a integer and a pointer is so different, I've also
wonderer whether to have two 'operators', INT_CAST() (or
INTEGRAL_CAST()?) and PTR_CAST(), to allow each form to be
found/undefined separately...
--
Alan J. McFarlane
http://www.alanjmcf.me.uk/
Please follow-up in the newsgroup for the benefit of all.

Nov 14 '05 #17

P: n/a

<Je***********@physik.fu-berlin.de> wrote in message
news:3g************@uni-berlin.de...
ju**********@yahoo.co.in wrote:
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.


Something must be wrong with your compiler since this shouldn't just
generate a warning but an error message.


The Standard only requires a diagnostic message. The Standard
makes no distinction between "error" or "warning" or any other
type of message.

Again...assuming the compiler being used is the Compaq C compiler
on Tru64, the compiler will emit two diagnostics for this program:

(int *)i_ptr = (char *) c_ptr; /* warning for this line */
1
(1) Info: In this statement, the result of the cast "(int ...)i_ptr" is used
as
an lvalue. (lvaluecast)

(1) Warning: In this statement, the referenced type of the pointer value
"(char
....)c_ptr" is "char", which is not compatible with "
int". (ptrmismatch)

Ed Vogel
HP/Compaq/DEC C/C++ Engineering
Nov 14 '05 #18

P: n/a
Keith Thompson wrote:
ju**********@yahoo.co.in writes:
I thank you all for your answers. From the various replies in this
thread what I concluded is that:

1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.

2) Sometimes while writing a piece of code that has to
directly access h/w (device drivers, embedded s/w) casts may be
the only option. In such cases, one must be aware of the consequences
of typecasting. Also, in such cases code review is the best
tool to find out such bugs. Compiler may not be issuing the
warning for all such *incompatible* casts.

That sounds about right.

Still I have one question. I might sound irritating but its better to
ask. Please bear with me. As most of you said that the compiler
didn't generate any warning because it was explicitly told to do
so. But there are other cases as well where explicit cast is done,
still the complier gives the warning.
eg.
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.

It might be helpful to mention what the warning says, but ...

I get:
jf.c:4: warning: assignment from incompatible pointer type

If you really want to do the assignment:
i_ptr = (int*)c_ptr;
should work.
Both the casts are no-ops; they convert a value of a given type to
that same type. If you're getting a warning about incompatible
pointer types, it has nothing to do with the casts. You'd get the
same warning without them.

But the most important point is that the assignment is illegal (though
some compilers may allow it as an extension). A cast is not an
lvalue, and cannot appear on the left side of an assignment, any more
than you can assign

x + 1 = 3;

If you invoke your compiler in conforming mode, it should reject the
assignment.


Yes. It must reject it. In an assignment, the lvalue is the object, not
the value it holds. For example:

int x = 1;
int y = 2;

if (x == 1)

treats the value of x.

x = y;

disregards the value of x. In this context x is an object, not a value.

(int)x = y;

This must fail because the cast creates a value where an object is required.

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #19

P: n/a
Ed Vogel <edward.vogel_stop_the_spam.@hp.com> wrote:
<Je***********@physik.fu-berlin.de> wrote in message
news:3g************@uni-berlin.de...
ju**********@yahoo.co.in wrote:
int main(void) {
char * c_ptr;
int * i_ptr;
(int *)i_ptr = (char *) c_ptr; /* warning for this line */
return(0);
}

compiling this code always generates warning.
Something must be wrong with your compiler since this shouldn't just
generate a warning but an error message.

The Standard only requires a diagnostic message. The Standard
makes no distinction between "error" or "warning" or any other
type of message. Again...assuming the compiler being used is the Compaq C compiler
on Tru64, the compiler will emit two diagnostics for this program: (int *)i_ptr = (char *) c_ptr; /* warning for this line */
1
(1) Info: In this statement, the result of the cast "(int ...)i_ptr" is used
as
an lvalue. (lvaluecast) (1) Warning: In this statement, the referenced type of the pointer value
"(char
...)c_ptr" is "char", which is not compatible with "
int". (ptrmismatch)


Ok, thanks;-)
Regard, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #20

P: n/a
ju**********@yahoo.co.in wrote:
Consider the following piece of code:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
Only, the typecasting to "char *" should be allowed which is
*guaranteed* to point to the lowest addressed byte of the structure.


Is this a troll? You explicitly told to cast the assigned address,
so why should you receive a warning? If you want to get warnings,
lose the casts. Typecasting to char* does not guarantee anything.
If you give it the address of one byte past the lowest byte of the
structure, it happily accepts that.

-atl-
--
A multiverse is figments of its own creations
Nov 14 '05 #21

P: n/a
Je***********@physik.fu-berlin.de writes:
ju**********@yahoo.co.in wrote:
1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.


Let's be a bit more pedantic and restrict that to pointer casts.
Casting "normal" values is quite common, you may often see in C89
programs e.g.

char hw[ ] = "Hello world!";
printf( "%lu\n", ( unsigned long ) strlen( hw );

to convert the size_t type return value of strlen() to something you
can print with one of the available format specifier (in C99 you bet-
ter would drop the cast and use "%zu" in the format string instead) or

double d = 42.1234;
int i = ( int ) d;

to assign the integer part of 'd' to 'i', snipping off the fractional
part.

And while casting pointers is often a sign of some trouble in a program,
there exist a few cases where they it's actually required, mostly in
conjunction with arguments of variadic functions.

[...]

Most casts are unnecessary because, in most contexts, the value will
be implicitly converted to the required type.

Variadic functions are probably the major exception to this rule. For
example, printf with a "%p" specifier expects a void*; if you want to
pass it an int*, you have to explicitly convert it. (A non-variadic
equivalent would convert from int* to void* implicitly.) printf with
a "%lu" expects an unsigned long; if you want to pass it a foo_t, you
have to convert it. (For size_t, C99 provides "%zu", but it can't
cover everything.)

If you see a cast in a context other than a call to a variadic
function, it's likely to be either unnecessary (specifying a
conversion that would have been done implicitly without the cast), or
potentially dangerous (performing a non-trivial conversion when it
very likely would have been better to use the correct type in the
first place).

In your example:

double d = 42.1234;
int i = ( int ) d;

the cast is actually unnecessary; it could have been written as

double d = 42.1234;
int i = d;

It's tempting to use the cast anyway, since it makes the conversion
expicit and numeric conversions aren't as dangerous as pointer
conversions. On the other hand, if during maintenance the type of
i is changed from int to long, but you forget to change the cast:

double d = 42.1234;
long i = ( int ) d;

you could be introducing a subtle bug that may be very difficult to
track down. (It's obvious in this example, but would be less so if
the assignments are far from the declarations.) That's another
drawback of the cast operator: the syntax requires you to specify the
target type by name, but sometimes what you really want is the type of
the target, whatever that happens to be. (A typeof operator might be
useful here -- not that I'm suggesting adding it to the language.)

One case where a numeric cast is necessary is when you want to control
when the conversion takes place. For example:

int x = 1;
int y = 3;
double z = (double)x/y;

Without the cast, z would be assigned the value 0.0.

By using a cast, you're promising the compiler that you know what
you're doing. You'd better be right.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #22

P: n/a
ju**********@yahoo.co.in wrote:

Consider the following piece of code:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
}

On compiling this program: cc -c99 -check -portable test.c
I don't get any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.

Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
But on compilation I don't get any warning message.

[...]

Because you have explicitly cast pstr_junk to (int *), you have basically
told the compiler "be quiet, I know what I'm doing".

If you had used an implicit cast:

i_ptr = pstr_junk;
i_ptr++;

then the compiler probably would be generating some nasty messages along
the lines of "are you sure you want to do this?"

On the other hand, is it undefined behavior when the first two members
of the struct are ints?

On the other other hand, it looks like what the code is trying to do is:

i_ptr = &(pstr_junk->i_val1);

which is perfectly legal and much clearer as to the intent.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Nov 14 '05 #23

P: n/a
On Sat, 04 Jun 2005 18:30:46 -0400, Kenneth Brody
<ke******@spamcop.net> wrote:
ju**********@yahoo.co.in wrote:

Consider the following piece of code:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
}

On compiling this program: cc -c99 -check -portable test.c
I don't get any warning.
However, the statement
i_ptr = (int *)pstr_junk + 1; seems to be incorrect to me.

Here, pstr_junk is a pointer to structure and it is being typecasted to
"int *" which may cause undefined behaviour.
But on compilation I don't get any warning message.

[...]

Because you have explicitly cast pstr_junk to (int *), you have basically
told the compiler "be quiet, I know what I'm doing".

If you had used an implicit cast:

i_ptr = pstr_junk;
i_ptr++;

then the compiler probably would be generating some nasty messages along
the lines of "are you sure you want to do this?"

On the other hand, is it undefined behavior when the first two members
of the struct are ints?

On the other other hand, it looks like what the code is trying to do is:

i_ptr = &(pstr_junk->i_val1);

which is perfectly legal and much clearer as to the intent.


But not necessarily the same result. There is no guarantee that
i_val1 immediately follows i_val since the compiler is free to insert
any padding it wants at this point.
<<Remove the del for email>>
Nov 14 '05 #24

P: n/a

On Sat, 4 Jun 2005, Keith Thompson wrote:
It's tempting to use the cast anyway, since it makes the conversion
expicit and numeric conversions aren't as dangerous as pointer
conversions. On the other hand, if during maintenance the type of
i is changed from int to long, but you forget to change the cast:


Can one then say that if there's any possibility that a type
might need to be changed for any reason, changing program requirements or
porting to a different platform, then a typedef should be used?

typedef int MyIntegerType /* change to 'long long' on a Whizbang-X100 */

...

MyIntegerType i;
double d = 12.345;

...

i = (MyIntegerType)d;

--
Nov 14 '05 #25

P: n/a
Kenneth Brody <ke******@spamcop.net> writes:
[...]
If you had used an implicit cast:

i_ptr = pstr_junk;
i_ptr++;

then the compiler probably would be generating some nasty messages along
the lines of "are you sure you want to do this?"


Correction: if you had used an implicit *conversion*. There's no such
thing as an implicit cast.

A cast is a source construct; the cast operator is a type name
enclosed in parentheses, preceding the operand. The operation that a
cast specifies is a conversion. Conversions can be explicit or
implicit (an explicit conversion is indicated by a cast operator).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #26

P: n/a

"pete" <pf*****@mindspring.com> wrote
>
> Learn more C.
>

What is the point of this reply?


The only way that you catch undefined behavior
that your compiler warnings miss, is by knowing enough C.
That's pretty much the whole point of reading this newsgroup.

If you look at what junky_fellow is doing, he seems to be playing games with
the C type system, maybe to work out what the underlying representation is
like. So why not tell him that the actual bit pattern and structure layout
varies from platform to platform, and that this is a surefire way to get
into trouble?

We've all got to learn, and at least he making some effort and not just
posting homework questions.
Nov 14 '05 #27

P: n/a
Keith Thompson wrote:
.... snip ...
One case where a numeric cast is necessary is when you want to
control when the conversion takes place. For example:

int x = 1;
int y = 3;
double z = (double)x/y;

Without the cast, z would be assigned the value 0.0.
Which cast can also be avoided by:

int x = 1;
int y = 3;
double z = x;

z /= y;
By using a cast, you're promising the compiler that you know
what you're doing. You'd better be right.


--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #28

P: n/a
Malcolm wrote:

"pete" <pf*****@mindspring.com> wrote
>
> Learn more C.
>
What is the point of this reply?
The only way that you catch undefined behavior
that your compiler warnings miss, is by knowing enough C.
That's pretty much the whole point of reading this newsgroup.

If you look at what junky_fellow is doing,
he seems to be playing games with
the C type system, maybe to work out what the underlying
representation is like.
So why not tell him that the actual bit pattern and structure layout
varies from platform to platform,
and that this is a surefire way to get into trouble?


I don't see what you see in junky_fellow's code.
I saw nothing that had to do with bit patterns.
It looked like portable C99 code to me.
We've all got to learn, and at least he making
some effort and not just posting homework questions.


I see no bugs here:

struct junk {
int i_val;
int i_val1;
char c_val;
};

int main(void)
{
struct junk str_junk;
int * i_ptr;
struct junk * pstr_junk;
pstr_junk = &str_junk;
i_ptr = (int *)pstr_junk + 1; /* shouldn't the compiler
give warning here ? */
}

--
pete
Nov 14 '05 #29

P: n/a
On Sun, 05 Jun 2005 21:36:25 +0000, CBFalconer wrote:
Keith Thompson wrote:

... snip ...

One case where a numeric cast is necessary is when you want to
control when the conversion takes place. For example:

int x = 1;
int y = 3;
double z = (double)x/y;

Without the cast, z would be assigned the value 0.0.


Which cast can also be avoided by:

int x = 1;
int y = 3;
double z = x;

z /= y;

By using a cast, you're promising the compiler that you know
what you're doing. You'd better be right


This is an example where the cast isn't particulatly bad, in fact I prefer
the cast form. It is clear and to the point. It is pointer casts that are
dangerous, casts between arithmetic types are usually benign - all such
conversions are allowed implcitly anyway. The only thing that avoiding the
cast protects you against in this example would be x being a pointer. That
could be a legitimate concern in some cases (e.g. catching (double *)*p
mistyped as (double *)p ) but it isn't usually a big deal.

So just because you can avoid casts doesn't mean that you automatically
should. You could avoid all of the casts in

printf("%.*lx %p\n", (int)prec, (unsigned long)size, (void *)ptr);

by assigning the values to variables of the appropriate type beforehand,
but sometimes casts are a good alternative, even for portable code.

Lawrence
Nov 14 '05 #30

This discussion thread is closed

Replies have been disabled for this discussion.