c prog -plz explain

S

SAHIL MAHLA

#include <stdio.h>
void incme(double *p)
{
*p += 1;
}

int main(void)
{
int i = 1;
double j=i;
incme((double*)&i);
printf("%d,%g",i,j);
return 0;
}

The output is :

0,1

I feel it should be :

2,1


Thanks in advance!!!
 
K

Keith Thompson

SAHIL MAHLA said:
#include <stdio.h>
void incme(double *p)
{
*p += 1;
}

int main(void)
{
int i = 1;
double j=i;
incme((double*)&i);
printf("%d,%g",i,j);
return 0;
}

The output is :

0,1

I feel it should be :

2,1

You posted this exact same program, with different output, in the other
thread. See Barry Schwarz's followup.

And please take the time to spell out words: "please" rather than "plz".
Silly abbreviations like that just make your text more difficult to
read.
 
L

Lew Pitcher

#include <stdio.h>
void incme(double *p)
{
*p += 1;
}

int main(void)
{
int i = 1;
double j=i;
incme((double*)&i);
printf("%d,%g",i,j);
return 0;
}

The output is :

0,1

I feel it should be :

2,1

Why do you feel that the program should print
2,1
as it's results? Please tell us your reasoning, so that we can assist you in
your understanding of the actual performance of your program code.

For what it's worth, others have told you *why* you get the results you get,
and *why* those results are questionable. Please re-read those responses,
and reconsider your "feeling".
 
B

Ben Bacarisse

Keith Thompson said:
You posted this exact same program, with different output, in the other
thread. See Barry Schwarz's followup.

This is a different program. This one is undefined because it converts
an 'int *' to a 'double *' and passes that to the incme function.

<snip>
 
B

Ben Bacarisse

Ben Bacarisse said:
Keith Thompson <[email protected]> writes:

This is a different program. This one is undefined because it converts
an 'int *' to a 'double *' and passes that to the incme function.

Ah, but this "different" program was also posted in the other thread!
Sorry for the noise.
 
S

SAHIL MAHLA

Why do you feel that the program should print

2,1

as it's results? Please tell us your reasoning, so that we can assist you in

your understanding of the actual performance of your program code.



For what it's worth, others have told you *why* you get the results you get,

and *why* those results are questionable. Please re-read those responses,

and reconsider your "feeling".



--

Lew Pitcher

"In Skills, We Trust"

PGP public key available upon request

Hi Pitcher ,

It's because we are typecasting i's address into a double* and then passing it to the incre() function. I know there is some issue with the typecasting itself.Passing like this is illegal ...is it???.....and my apologies for the silly abbrevations.
 
S

SAHIL MAHLA

This is a different program. This one is undefined because it converts

an 'int *' to a 'double *' and passes that to the incme function.



<snip>

Hi Ben ,

Yes we are converting a int* to double*.Could you generalize this with a rule why that is undefined.
 
I

Ian Collins

It's because we are typecasting i's address into a double* and then passing it to the incre() function. I know there is some issue with the typecasting itself.Passing like this is illegal ...is it???.....and my apologies for the silly abbrevations.

Please trim you quotes and cleanup all the unwanted blank lines that
awful google interface adds!

You are "casting", not "typecasting".

You are passing the address of an int, which probably has a size of 4 to
a function expecting the address of a double, which probably has a size
of 8. Consider what happens when 8 bytes are written to something 4
bytes long...
 
J

James Kuyper

Hi Ben ,
Yes we are converting a int* to double*.Could you generalize this with a rule why that is undefined.

A pointer to an object of one type can be converted to a pointer to an
object with a completely unrelated type. However, if the pointer is not
correctly aligned for the new type, the behavior of the conversion is
undefined. (6.3.2.3p7) That could apply here, but it's not the most
serious problem you face.

The really serious problem is that most objects have an effective type
(the only exception is dynamically allocated memory that has not yet
been accessed using a pointer to a non-character type). If you attempt
to access an object with one types, using an lvalue of a different type,
it is called type punning. The result of type punning is usually
undefined behavior. In this case, the effective type of 'i' is the same
as it's declared type, 'int'. The expression *p is an lvalue of type
double. Therefore, attempting to access the memory set aside to hold
'i', using the expression *p, has undefined behavior.

It is possible to use type punning safely. However, unless one of the
two types involved is a character type, they must be closely related
types, and 'int' is completely unrelated to 'double'. The precise rules
are given in 6.5p7, but until you've learned those rules, the safest
course is to avoid type punning.

The basic reason for this rule is simple. Any object in C is represented
by a series of bytes. For each object type, there is some precise rule
that connects the value of each byte, and the value represented by that
object, and it's generally a completely different rule for objects of
different types. Type punning takes bytes that represented one value
according to the rules for one type, and reinterprets them as if they
represented a value according to the rules of a different type. This
obviously can't work if the new type is larger than the original type,
but even if they are the same size, it can fail, in some cases
catastrophically. C's rules define the cases where you can portably rely
upon type punning to work in some useful fashion.
 
K

Kaz Kylheku

Yes we are converting a int* to double*.Could you generalize this with a rule
why that is undefined.

Yes. The rule is written in a document called ISO 9899 ("International
Standard -- Programming Languages -- C").

It was first published in 1990 (ISO 9899:1990) and describes a language called C90.
It was updated to ISO 9899:1999 (C99), and 2011 (C11).

If you read the standard, you will learn about all kinds of rules.

It's really too complicated (and more importantly inefficient) to lecture about
in a series of Usenet articles to complete newbies. Why don't you read the document,
and then if you have questions, then it makes for a better discussion
than "spoon feed me the rules", know what I mean?

The rule which applies here is that an object shall not be accessed through an
lvalue which is not its declared type (or a const/volatile qualified version of
its declared type). An object of type int being accessed as if it were an object
of type double results in undefined behavior.

C is a strongly typed language. It has the concept of type: that an operation
of the correct type must be applied to a datum for well-defined behavior. C has
considerable translation-time type checking in it to support its type system,
but when you use casts, especially for conversions among pointer types, you can
defeat the type system and write programs which break the rules, but do not
produce any diagnostics when compiled, and even make an executable.
 
K

Kaz Kylheku

Hi Pitcher ,

It's because we are typecasting i's address into a double* and then passing
it to the incre() function. I know there is some issue with the typecasting
itself.Passing like this is illegal ...is it???.....and my apologies for the
silly abbrevations.

Never mind the type casting being illega.

Have you considerd that the type double and the type int do not even have the
same size? (They might, but often they do not. A common size for int is 32
bits nowadays, and a double is often 64 bits.)

What do you think happens when you pass a pointer to 32 bytes of storage
to a function which treats that as 64 bytes of storage?
Of course, that function stomps on memory outside of the object.

The code could well crash. What if incme overwrites the return address on the
stack, so that when it tries to return back to main, it jumps into nowhere
land, resulting in an access violation or illegal instruction trap or something
of that sort?

Listen, you better start replacing "I feel" with "I think", or find another
hobby.

Then, have you considered byte order issues? Suppose that the previous issue is
not a problem. Although incme stomps over memory beyond the boundaries of i,
let's suppose there is no problem because, let's say that that memory is just
some unused padding space or whatever. There is still the problem that on
some machines, values are laid out with the least significant bits at the base
address. On other machines, values are placed with the most significant bits
at the base address. This means that the int object i, if it is smaller than
double (like 32 bits versus 64), could correspond to the upper half of double,
where the sign and exponent are, or it could correspond to the lower half,
where there are mantissa bits.

Then there is the issue that incrementing a floating-point value by 1.0 is
completely different from incrementing an integer by 1.

Consider that if you add 1.0 to some really huge number like 1.0E+256,
it doesn't change at all, because 1.0 is too small in comparison.

However, if you add 1.0 to a really small number (close to zero) like
1.0E-256, the result is just 1.0 because the really small number
vanishes next to 1.0.

Which bits of the floating-point value are affected when 1.0 is added
to it (if any) and in what ways depends on the value. Adding 1.0
might change the exponent field, or it might not. It could change
the most significant bits of the mantissa, or the least significant
bits, or none at all.

Adding 1 to a postive integer is (in the absence of overflow) a purely
binary operation. The least significant bit increments, and if that
overflows, the next bit increments, and so on.

The two operations are not related at all, and so if you perform a floating
point increment on an integer or vice versa, you can get some very strange
results.
 
K

Kaz Kylheku

Don't give up your day job Kaz. Your insightful, friendly and, above
all, helpful & professional input would be missed here.

Are you saying that I couldn't be here if I didn't have a day job?

Or that ... this *is* my day job?

Must be the second thing; the first is not known to be a significant barrier to
Usenet participation.

You don't get much income around here, but today we have "incme".
Double star, too!
There was a time these groups were here to help and correct.

I've been here since 1994 or 1995, so it must have been before then.
 
B

BartC

Yes we are converting a int* to double*.Could you generalize this with a
rule why that is undefined.

Because ints and doubles have a completely different binary representation.

You might be /casting/ a pointer to int, to a pointer to double, but you are
/type-punning/ what it points to. (You can't do an in-place cast of a
pointer's target value.)

The result will be meaningless unless you have a clue as to what you are
doing, and do it properly. It can also cause problems (not just wrong
results), if doubles are 8 bytes and ints are 4 bytes, because the *p+=1
line might cause 8 bytes to updated at i, but i only has 4 bytes reserved
for it.

You don't need to read 700 pages of C specification to know that you cannot
tell what will happen!
 
L

Lew Pitcher

Hi Pitcher ,

It's because we are typecasting i's address into a double* and then
passing it to the incre() function.

What effect do you think that
(double*)&i
has on
i
?

In other words, what do you think that the "typecasting" (sic) does?
Does it affect the storage type? Does "typecasting" a
pointer to an integer
to a
pointer to a double precision floating point
change the allocation of the thing pointed to from
integer
to
double precision floating point
?
I know there is some issue with the
typecasting itself. Passing like this is illegal ...is it???

No one is going to arrest you for it; there is no law against it.

And "typecasting" (sic), as a tool, does not violate any requirements of the
C language.

But, just as a stick of dynamite can cause unintended damage when used
incorrectly, "typecasting" (sic) also has it's dangerous side. It is not in
the facility, but in it's use, that the danger occurs. And, your use
of "typecasting" (sic) shows that you not only do not understand what it
does, you have a misconception that has resisted all our attempts here to
correct.
.....and my apologies for the silly abbrevations.

Don't apologize. Just stop.

You may have noticed my use of quotes and the editor's note "sic" when I use
your word "typecasting". Computer programs are literal; they do not
tolerate typographic errors, creative spelling, or incorrect terms.
Programmers tend to become pedantic regarding the misuse of terminology and
intentional misuse of grammer or syntax.

The term is "casting", not "typecasting". True, a "cast" changes the "type"
of a value (a *value*, not an *object*), but to call the construct
a "typecast" is just wrong.
 
B

Ben Bacarisse

It's because we are typecasting i's address into a double* and then
passing it to the incre() function. I know there is some issue with
the typecasting itself.Passing like this is illegal ...is it???

An analogy. Think of a pointer as a handle -- a literal handle. Your
car has a handbrake and a gearbox:

handbreak brake = 1; // handbrake is on
gearbox gbox = 3; // car is in 3rd gear

The pointer &b is the handbrake lever -- it's attached to the actual
brake. &g is the gear stick -- attached to the gear box. You can do
gearbox-like things using a handle to a gearbox object, and you can do
brake-like things using a handbrake handle. But writing:

gearbox *stick = (gearbox *)&brake;

is like making something that looks like a gear stick and attaching it
to the brakes. Trying the usual action to put the car into 4th using
this handle will just break stuff.
 
K

Ken Brody

#include <stdio.h>
void incme(double *p)
{
*p += 1;
}

int main(void)
{
int i = 1;
double j=i;
incme((double*)&i);
printf("%d,%g",i,j);
return 0;
}
[...]

"I took my box of salt, and with a marker I crossed out 'salt' and wrote
'sugar'. How come my tea tastes funny?"

Just because you told the compiler to treat the pointer-to-int "&i" as if it
were a pointer-to-double doesn't mean that what it points to really *is* a
double.
 
K

Keith Thompson

Ken Brody said:
#include <stdio.h>
void incme(double *p)
{
*p += 1;
}

int main(void)
{
int i = 1;
double j=i;
incme((double*)&i);
printf("%d,%g",i,j);
return 0;
}
[...]

"I took my box of salt, and with a marker I crossed out 'salt' and wrote
'sugar'. How come my tea tastes funny?"

Just because you told the compiler to treat the pointer-to-int "&i" as if it
were a pointer-to-double doesn't mean that what it points to really *is* a
double.

Sahil: If you're new to the language, I suggest you'll have better luck
taking something you want to do and then figuring out how to do it,
rather than starting with some (in this case questionable) code and then
trying to figure out how it behaves and why.

Yet another silly analogy: If you have a hammer, you should probably try
to learn how to drive nails with it rather than starting out by asking
what happens if you try to drive screws with it. You'll have plenty of
opportunity to screw things up once you've mastered the basics.

And again, let me recommend http://www.c-faq.com/ as an excellent
resource (though as the name implies it's a collection of questions and
answers, not a tutorial).
 
G

glen herrmannsfeldt

(snip)
Sahil: If you're new to the language, I suggest you'll have better luck
taking something you want to do and then figuring out how to do it,
rather than starting with some (in this case questionable) code and then
trying to figure out how it behaves and why.
Yet another silly analogy: If you have a hammer, you should probably try
to learn how to drive nails with it rather than starting out by asking
what happens if you try to drive screws with it. You'll have plenty of
opportunity to screw things up once you've mastered the basics.

It would help if Sahil explained any previous programming experience.

I can imagine someone with years of experience in other languages
suddenly being surprised by the way C works, but also someone with no
experience at all in other langauges.

Explaining the reason why things work the way they do is different
in the two cases.

I didn't start with C until some years of programming, including
enough assembly programming that I was used to thinking about
addresses of things. (Though it took me a little while with my
first assembly programs to remember which address was doing what.)

(snip)

-- glen
 
K

Kaz Kylheku

It would help if Sahil explained any previous programming experience.

I can imagine someone with years of experience in other languages
suddenly being surprised by the way C works, but also someone with no
experience at all in other langauges.

Explaining the reason why things work the way they do is different
in the two cases.

I didn't start with C until some years of programming, including
enough assembly programming that I was used to thinking about
addresses of things. (Though it took me a little while with my

But that type of experience can also make some people more convinced
about what something "should" do in C.

The reason why explaining the reasons is different for the two cases
is that in the case of the fresh newbie, you just have to explain it.

In the case of the experienced newbie, you have to explain it,
and furthermore, argue it ad nauseum. :)
 
J

Jorgen Grahn

SAHIL MAHLA wrote: ....
It's because we are typecasting i's address into a double* and [...]
You are "casting", not "typecasting".

For the record, I sometimes say "typecast" too. Picked it up 25 years
ago or so, probably from my teachers. I'm tempted to suggest that it
should be tolerated as a nickname ...

/Jorgen
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top