# difference between pointers

Discussion in 'C Programming' started by Varun Tewari, Mar 30, 2013.

1. ### Varun TewariGuest

hello all,

consider the following code.

int a,b,d1,d2,diff;

d1= &a;
d2 = &b;
diff = &a-&b;
diff = d1-d2;
printf("\nDifference between address(stored in integers): %d", diff);

ideally, both printf should result same output.
but as expected diff = d1-d2 gives 4.
but diff = &a-&b gives 1.

Varun Tewari, Mar 30, 2013

2. ### Eric SosmanGuest

On 3/30/2013 11:36 AM, Varun Tewari wrote:
> hello all,
>
>
> consider the following code.
>
> int a,b,d1,d2,diff;
>
> d1= &a;
> d2 = &b;
> diff = &a-&b;
> printf("\nDifference between address: %d", diff);
> diff = d1-d2;
> printf("\nDifference between address(stored in integers): %d", diff);
>
> ideally, both printf should result same output.
> but as expected diff = d1-d2 gives 4.
> but diff = &a-&b gives 1.
>

that the code's behavior is undefined: The C language doesn't
specify what should happen, so *anything* might happen.

First, pointer arithmetic always operates in units of the
to the next `int', adding 1 to a `double*' advances to the next
`double', and so on. Even if an `int' occupies four bytes and
proper distance for its type.

... so subtraction works the same way: If you start with an
`int*', add 1 to produce another pointer to the next `int', and
then subtract the two values, what do you get? You get 1: the
distance between the two objects is expressed in multiples of
the object size. If you start with a pointer `p' and derive a
new pointer `q' by computing `q = p + 3', it should come as no
surprise that `q - p' yields 3.

However, this adding and subtracting only works when you're
navigating within in an array that contains the pointed-at objects.
That's the only way to be sure of the right adjacency and spacing
that allows pointer arithmetic to be defined. Consider: If you
have two objects that are six bytes long, and if they exist at
addresses eight bytes apart, the distance between them is not a
multiple of the size and pointer arithmetic falls down: You can't
add 1 to a pointer and have it advance by one-and-a-third objects!

... and that's where the undefined behavior enters your code.
Since `a' and `b' are free-standing objects, unrelated to each
other and not part of the same array, subtracting pointers to them
cannot be guaranteed to produce a sensible answer. So C does not
promise that anything sensible will happen; C says "the behavior
is undefined" and just leaves it at that. In your case it seems
that `a' and `b' did in fact wind up in adjacent memory regions,
but that's a coincidence, not something C promises nor that you
can rely on.

Next topic: Why 1 vs. 4?

C promises that a pointer can be converted to some kind of
integer, but says very little about how wide an integer is needed
and says nothing at all about the nature of the conversion. You
take a pointer, convert it to an `int', and you get some kind of
value. (It is not even guaranteed that you'll get the same value
every time!) In your case, it seems that the address part of your
pointer (or part of it) simply got transliterated into a bag of
bits that were then interpreted as an `int' value -- that's a very
common scheme, but not the only one.

But notice what's left behind: The pointer "knew" what kind
of object it pointed to, and hence the size of that object, and
thus knew how to compensate for that size when doing arithmetic.
The `int' resulting from conversion, though, has no information
about the type of object the pointer aimed at, and cannot make
adjustments for object size. So when you subtract the integers
there's no adjustment: You get the distance between the objects
expressed not in object-units, but in bytes (again, this is a
common outcome but not the only possibility).

--
Eric Sosman
d

Eric Sosman, Mar 30, 2013

3. ### Tim RentschGuest

Varun Tewari <> writes:

> hello all,
>
>
> consider the following code.
>
> int a,b,d1,d2,diff;
>
> d1= &a;
> d2 = &b;
> diff = &a-&b;
> printf("\nDifference between address: %d", diff);
> diff = d1-d2;
> printf("\nDifference between address(stored in integers): %d", diff);
>
> ideally, both printf should result same output.
> but as expected diff = d1-d2 gives 4.
> but diff = &a-&b gives 1.
>

Compiling this code should have produced at least one warning or
error message. If it did not, you are very likely operating the
compiler in a non-conforming mode; in other words, the language
accepted may look a lot like C, but it isn't C.

If the compiler you are using is gcc, try these options:

gcc -ansi -pedantic-errors

which directs gcc to operate according to how standard C is
defined, rather than the "C-like but not C" language that
gcc accepts by default.

Tim Rentsch, Mar 30, 2013
4. ### Tim RentschGuest

Eric Sosman <> writes:

> On 3/30/2013 11:36 AM, Varun Tewari wrote:
>> hello all,
>>
>>
>> consider the following code.
>>
>> int a,b,d1,d2,diff;
>>
>> d1= &a;
>> d2 = &b;
>> diff = &a-&b;
>> printf("\nDifference between address: %d", diff);
>> diff = d1-d2;
>> printf("\nDifference between address(stored in integers): %d", diff);
>>
>> ideally, both printf should result same output.
>> but as expected diff = d1-d2 gives 4.
>> but diff = &a-&b gives 1.
>>

>
> that the code's behavior is undefined: The C language doesn't
> specify what should happen, so *anything* might happen.

Except that, before getting to that point, a diagnostic is
required -- assigning an integer to a pointer is a constraint
violation.

> [snip]
>
> C promises that a pointer can be converted to some kind of
> integer, but says very little about how wide an integer is needed
> and says nothing at all about the nature of the conversion. You
> take a pointer, convert it to an `int', and you get some kind of
> value. (It is not even guaranteed that you'll get the same value
> every time!) In your case, it seems that the address part of your
> pointer (or part of it) simply got transliterated into a bag of
> bits that were then interpreted as an `int' value -- that's a very
> common scheme, but not the only one.

This is right in spirit but a lot of the details are wrong.

C does promise that a pointer can be converted to one particular
integer type; however, the conversion is completely specified,
as is the width of the integer, because the type in question is
the "boolean" type _Bool. The Standard does not guarantee that
a pointer can be converted to any other integer type.

If the header file <stdint.h> defines the types intptr_t,
then these types are guaranteed to work for converting any valid
pointer to void (ie, any valid pointer value of type 'void *');
moreover, converting back the other direction is guaranteed to
compare equal to the original pointer value.

There is no guarantee that a pointer to any type other than
void can be converted to any integer type other than _Bool. A
pointer to void can be converted to the types intptr_t, but
only if the implementation defines them, which the Standard
does not require.

On the flip side, the result of converting a pointer to an
integer type is implementation-defined, which means each
implementation has to document what it does. So, for any
specific implementation, you can find out which integer types
may be used to convert different kinds of pointer values, and
what the result of those conversions will be.

Tim Rentsch, Mar 30, 2013
5. ### Keith ThompsonGuest

Eric Sosman <> writes:
> On 3/30/2013 11:36 AM, Varun Tewari wrote:
>>
>> consider the following code.
>>
>> int a,b,d1,d2,diff;
>>
>> d1= &a;
>> d2 = &b;
>> diff = &a-&b;
>> printf("\nDifference between address: %d", diff);
>> diff = d1-d2;
>> printf("\nDifference between address(stored in integers): %d", diff);

[SNIP]
> Next topic: Why 1 vs. 4?
>
> C promises that a pointer can be converted to some kind of
> integer, but says very little about how wide an integer is needed
> and says nothing at all about the nature of the conversion. You
> take a pointer, convert it to an `int', and you get some kind of
> value. (It is not even guaranteed that you'll get the same value
> every time!) In your case, it seems that the address part of your
> pointer (or part of it) simply got transliterated into a bag of
> bits that were then interpreted as an `int' value -- that's a very
> common scheme, but not the only one.

You're assuming that this:

d1 = &a; /* where d1 and a are both of type int */

specifies a conversion. Nothing in the C standard says or implies
that. The types int and int* are not assignment-compatible, so
the assignment is a constraint violation, requiring a diagnostic.
*If* the compiler chooses to generate an executable after issuing
the diagnostic, nothing in the C standard says anything about how
it behaves.

It happens that, in most implementations, the behavior is equivalent
to:

d1 = (int)&a;

for historical reasons. But you shouldn't depend on that; a
conforming implementation could do *anything*. Don't waste your
time running the program, just fix the source code.

And in this case, the best fix is almost certainly *not* to add
the cast (adding casts to silence warnings is rarely a good idea),
but to change the declaration of d1.

(I'm leaving aside the fact that the behavior of `&a - &b` is
undefined; others have covered that.)

[...]

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Mar 30, 2013
6. ### BartCGuest

"Varun Tewari" <> wrote in message
news:...
> hello all,
>
>
> consider the following code.
>
> int a,b,d1,d2,diff;
>
> d1= &a;
> d2 = &b;
> diff = &a-&b;
> printf("\nDifference between address: %d", diff);
> diff = d1-d2;
> printf("\nDifference between address(stored in integers): %d", diff);
>
> ideally, both printf should result same output.
> but as expected diff = d1-d2 gives 4.
> but diff = &a-&b gives 1.
>

C likes to do pointer arithmetic in terms of 'objects' rather than bytes.
&a-&b gives the difference in number of objects (and a, b happen to be next
to each in memory, so one object difference).

While d1-d2 subtracts one byte address from another, after each is converted
to a plain int so that it no longer knows what kinds of pointers they were.

It would be a little more interesting if a and b weren't aligned on a 4-byte
boundary, and the byte-difference in their addresses wasn't a multiple of 4.
(For this sort of reason, I'd have preferred pointer arithmetic to work in
bytes, or rather chars, but using objects has its advantages too.)

--
Bartc

BartC, Mar 30, 2013
7. ### Tim RentschGuest

Keith Thompson <> writes:

> Eric Sosman <> writes:
>> On 3/30/2013 11:36 AM, Varun Tewari wrote:
>>>
>>> consider the following code.
>>>
>>> int a,b,d1,d2,diff;
>>>
>>> d1= &a;
>>> d2 = &b;
>>> diff = &a-&b;
>>> printf("\nDifference between address: %d", diff);
>>> diff = d1-d2;
>>> printf("\nDifference between address(stored in integers): %d", diff);

> [SNIP]
>> Next topic: Why 1 vs. 4?
>>
>> C promises that a pointer can be converted to some kind of
>> integer, but says very little about how wide an integer is needed
>> and says nothing at all about the nature of the conversion. You
>> take a pointer, convert it to an `int', and you get some kind of
>> value. (It is not even guaranteed that you'll get the same value
>> every time!) In your case, it seems that the address part of your
>> pointer (or part of it) simply got transliterated into a bag of
>> bits that were then interpreted as an `int' value -- that's a very
>> common scheme, but not the only one.

>
> You're assuming that this:
>
> d1 = &a; /* where d1 and a are both of type int */
>
> specifies a conversion. Nothing in the C standard says or implies
> that. The types int and int* are not assignment-compatible, so
> the assignment is a constraint violation, requiring a diagnostic.
> *If* the compiler chooses to generate an executable after issuing
> the diagnostic, nothing in the C standard says anything about how
> it behaves. [...] a conforming implementation could do *anything*.
> [snip elaboration]

I'm not sure what your reasoning is to reach this conclusion.
Certainly this assignment has a constraint violation, but you're
saying, in effect, that it has undefined behavior. Presumably
the underlying reasoning is one of two things, namely:

A. There is a constraint violation, and any constraint
violation is necessarily undefined behavior; or

B. The assignment statement is trying to assign a pointer
type to an integer type, and nothing in the Standard
says how to do that, so there is undefined behavior.

IMO point A is incorrect, although I would agree the point
is debatable. Section 4 paragraph 3 says in part:

If a ``shall'' or ``shall not'' requirement that appears
outside of a constraint or runtime-constraint is violated,
the behavior is undefined.

This statement makes it reasonable to infer that a constraint
violation might _not_ result in undefined behavior in some
instances, as otherwise there is no point in excluding it.
("The exception proves the rule in cases not excepted.")

Turning to point B, I think it is clearly just wrong, because
of 6.5.16.1 p 2.

Aside from the constraint violation, I don't see anything that
makes this assignment have undefined behavior. If it is true
that a constraint violation is not /ipso facto/ undefined
behavior, then the behavior of this assignment is well-defined.
A compiler is free to reject it (with the necessary diagnostic)
because of the constraint violation; but if the compiler chooses
to accept it, then the assignment must behave the same way that

d1 = (int) &a;

would.

Tim Rentsch, Mar 30, 2013
8. ### Varun TewariGuest

Yep it did give warning.Thnx for pointing the correct gcc option for correct ansi parsing.

Varun Tewari, Mar 31, 2013
9. ### Keith ThompsonGuest

Tim Rentsch <> writes:
> Keith Thompson <> writes:

[...]
>> You're assuming that this:
>>
>> d1 = &a; /* where d1 and a are both of type int */
>>
>> specifies a conversion. Nothing in the C standard says or implies
>> that. The types int and int* are not assignment-compatible, so
>> the assignment is a constraint violation, requiring a diagnostic.
>> *If* the compiler chooses to generate an executable after issuing
>> the diagnostic, nothing in the C standard says anything about how
>> it behaves. [...] a conforming implementation could do *anything*.
>> [snip elaboration]

>
> I'm not sure what your reasoning is to reach this conclusion.
> Certainly this assignment has a constraint violation, but you're
> saying, in effect, that it has undefined behavior. Presumably
> the underlying reasoning is one of two things, namely:
>
> A. There is a constraint violation, and any constraint
> violation is necessarily undefined behavior; or
>
> B. The assignment statement is trying to assign a pointer
> type to an integer type, and nothing in the Standard
> says how to do that, so there is undefined behavior.
>
> IMO point A is incorrect, although I would agree the point
> is debatable. Section 4 paragraph 3 says in part:
>
> If a ``shall'' or ``shall not'' requirement that appears
> outside of a constraint or runtime-constraint is violated,
> the behavior is undefined.

IMHO A is correct (programs with constraint violations have undefined
behavior), though I'm not sure I can prove it.

> This statement makes it reasonable to infer that a constraint
> violation might _not_ result in undefined behavior in some
> instances, as otherwise there is no point in excluding it.
> ("The exception proves the rule in cases not excepted.")

Perhaps, but only if the behavior is actually defined somewhere.

> Turning to point B, I think it is clearly just wrong, because
> of 6.5.16.1 p 2.

Which says:

In *simple assignment* (=), the value of the right operand is
converted to the type of the assignment expression and replaces the
value stored in the object designated by the left operand.

That's an interesting point, but consider the definition of "constraint"
in 3.8:

restriction, either syntactic or semantic, by which the exposition
of language elements is to be interpreted

So the statement about the semantics of a simplea ssignment "is to
be interpreted" in the context of the restriction on the operands.
My conclusion from that is that if the constraint is violated,
the statement doesn't apply.

If the constraint is violated, it isn't a simple assignment.
We don't know what it is, but it's not part of a valid C program.

A compiler is free to reject a program containing such an assignment.
If it does so, the conversion described in 6.5.16.1p2 does not
occur -- but that doesn't mean the compiler is non-conforming.

I suppose you could (and apparently do) interpret it to mean that
the conversion occurs *if* the program is not rejected. I find
that interpretation a bit strained.

> Aside from the constraint violation, I don't see anything that
> makes this assignment have undefined behavior. If it is true
> that a constraint violation is not /ipso facto/ undefined
> behavior, then the behavior of this assignment is well-defined.
> A compiler is free to reject it (with the necessary diagnostic)
> because of the constraint violation; but if the compiler chooses
> to accept it, then the assignment must behave the same way that
>
> d1 = (int) &a;
>
> would.

I disagree.

Note also that, quoting 4p6:

A conforming implementation may have extensions [...] provided they
do not alter the behavior of any strictly conforming program.

which implies that such an extension *could* alter the behavior of a
program containing such an assignment.

(It could also imply that an extension could alter the behavior
of printf("%d\n", INT_MAX), which I find a bit troubling. I'm not
sure that strict conformance was the best criterion to use there.)

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Mar 31, 2013
10. ### Joe PfeifferGuest

"christian.bau" <> writes:

> On Mar 30, 3:36Â pm, Varun Tewari <> wrote:
>> hello all,
>>

>
> You don't have a doubt, you have a question. A "doubt" is a "feeling
> of uncertainty or lack of conviction".

There are areas of the world in which "doubt" is used exactly as
Americans and Europeans use "question". This was one of the things I
had to get used to when I started having significant numbers of students
from India.

Joe Pfeiffer, Mar 31, 2013
11. ### Kenny McCormackGuest

I have a doubt... (Was: difference between pointers)

In article <>,
Joe Pfeiffer <> wrote:
>"christian.bau" <> writes:
>
>> On Mar 30, 3:36Â pm, Varun Tewari <> wrote:
>>> hello all,
>>>

>>
>> You don't have a doubt, you have a question. A "doubt" is a "feeling
>> of uncertainty or lack of conviction".

>
>There are areas of the world in which "doubt" is used exactly as
>Americans and Europeans use "question". This was one of the things I
>had to get used to when I started having significant numbers of students
>from India.

Which leads inevitably to the ago-old question. Say you find yourself in a
situation where, speaking on the topic of dogs, large numbers of people call
a tail a "leg". Do you accept that as acceptable usage and go along with
the crowd, or do you patiently instruct them, over and over, that a tail is
not a leg?

And note, given that in this newsgroup, people never get tired of bitching
about "void main" or telling people not to cast the return value of malloc,
or about how not #includ'ing stdio.h causes undefined behavior, I don't
think there's much likelihood they'll stop bitching about people misusing
the word "doubt".

people not
--
A liberal, a moderate, and a conservative walk into a bar...

Bartender says, "Hi, Mitt!"

Kenny McCormack, Apr 1, 2013
12. ### Joe PfeifferGuest

Re: I have a doubt...

(Kenny McCormack) writes:

> In article <>,
> Joe Pfeiffer <> wrote:
>>"christian.bau" <> writes:
>>
>>> On Mar 30, 3:36Ã‚Â pm, Varun Tewari <> wrote:
>>>> hello all,
>>>>
>>>
>>> You don't have a doubt, you have a question. A "doubt" is a "feeling
>>> of uncertainty or lack of conviction".

>>
>>There are areas of the world in which "doubt" is used exactly as
>>Americans and Europeans use "question". This was one of the things I
>>had to get used to when I started having significant numbers of students
>>from India.

>
> Which leads inevitably to the ago-old question. Say you find yourself in a
> situation where, speaking on the topic of dogs, large numbers of people call
> a tail a "leg". Do you accept that as acceptable usage and go along with
> the crowd, or do you patiently instruct them, over and over, that a tail is
> not a leg?
>
> And note, given that in this newsgroup, people never get tired of bitching
> about "void main" or telling people not to cast the return value of malloc,
> or about how not #includ'ing stdio.h causes undefined behavior, I don't
> think there's much likelihood they'll stop bitching about people misusing
> the word "doubt".

Those are legitimate concerns about C.

Joe Pfeiffer, Apr 1, 2013
13. ### Keith ThompsonGuest

"BartC" <> writes:
> "Varun Tewari" <> wrote in message
> news:...
>>
>> consider the following code.
>>
>> int a,b,d1,d2,diff;
>>
>> d1= &a;
>> d2 = &b;
>> diff = &a-&b;
>> printf("\nDifference between address: %d", diff);
>> diff = d1-d2;
>> printf("\nDifference between address(stored in integers): %d", diff);
>>
>> ideally, both printf should result same output.
>> but as expected diff = d1-d2 gives 4.
>> but diff = &a-&b gives 1.
>>

>

The "-" operator actually is overloaded: it can be applied to
integers, floating-point values, or pointers. What C doesn't

> C likes to do pointer arithmetic in terms of 'objects' rather than bytes.
> &a-&b gives the difference in number of objects (and a, b happen to be next
> to each in memory, so one object difference).
>
> While d1-d2 subtracts one byte address from another, after each is converted
> to a plain int so that it no longer knows what kinds of pointers they were.
>
> It would be a little more interesting if a and b weren't aligned on a 4-byte
> boundary, and the byte-difference in their addresses wasn't a multiple of 4.
> (For this sort of reason, I'd have preferred pointer arithmetic to work in
> bytes, or rather chars, but using objects has its advantages too.)

The main purpose of pointer arithmetic is to access elements within
arrays. For example, the indexing operator [] is defined in terms
of pointer arithmetic. The distance between elements of an array
is always a whole multiple of the size of each element.

If you want the difference *in bytes* between two pointer values,
you can just convert both pointers to char*.

Yes, pointer arithmetic could have been defined in terms of bytes, but
it's more convenient the way it is.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Apr 1, 2013
14. ### Øyvind RøtvoldGuest

Re: I have a doubt... (Was: difference between pointers)

(Kenny McCormack) writes:

[ ... ]
> Which leads inevitably to the ago-old question. Say you find yourself in a
> situation where, speaking on the topic of dogs, large numbers of people call
> a tail a "leg". Do you accept that as acceptable usage and go along with
> the crowd, or do you patiently instruct them, over and over, that a tail is
> not a leg?

Or perhaps: Say you find yourself in a situation where, speaking on
the topic of "hunds", large numbers of people call a "shank" a "leg".
Do you accept that as acceptable usage and go along with the crowd, or
do you patiently instruct them, over and over, that a leg is not a
shank? And when you've given up on that someone starts to call a
"hund" a "dog", and here we go again.

--
... Øyvind - soon to appear in a kill file near you.
... Ignorance can be cured; stupidity is forever.

Øyvind Røtvold, Apr 1, 2013
15. ### Kenny McCormackGuest

Re: I have a doubt... (Was: difference between pointers)

In article <>,
Øyvind Røtvold <> wrote:
>
> (Kenny McCormack) writes:
>
>[ ... ]
>> Which leads inevitably to the ago-old question. Say you find yourself in a
>> situation where, speaking on the topic of dogs, large numbers of people call
>> a tail a "leg". Do you accept that as acceptable usage and go along with
>> the crowd, or do you patiently instruct them, over and over, that a tail is
>> not a leg?

>
>Or perhaps: Say you find yourself in a situation where, speaking on
>the topic of "hunds", large numbers of people call a "shank" a "leg".
>Do you accept that as acceptable usage and go along with the crowd, or
>do you patiently instruct them, over and over, that a leg is not a
>shank? And when you've given up on that someone starts to call a
>"hund" a "dog", and here we go again.

Or you could just say "To heck with it all" and go back to bitching about
void main() and casting the return value of malloc().

--
Modern Christian: Someone who can take time out from
complaining about "welfare mothers popping out babies we
have to feed" to complain about welfare mothers getting
abortions that PREVENT more babies to be raised at public
expense.

Kenny McCormack, Apr 1, 2013
16. ### Varun TewariGuest

Re: I have a doubt... (Was: difference between pointers)

Thnx Everyone.

For me my doubts are cleared, and for those who think it wasn't a doubt but a question, yes my questions are well answered.

Varun Tewari, Apr 1, 2013
17. ### Tim RentschGuest

Varun Tewari <> writes:

> Yep it did give warning. Thnx for pointing the correct gcc option for
> correct ansi parsing.

You may also want to try

gcc -std=c99 -pedantic-errors

or (if you have a newer version of gcc)

gcc -std=c11 -pedantic-errors

instead of using -ansi, which specifies the 1990 version of ISO C.

Tim Rentsch, Apr 2, 2013
18. ### Tim RentschGuest

Keith Thompson <> writes:

> Tim Rentsch <> writes:
>> Keith Thompson <> writes:

> [...]
>>> You're assuming that this:
>>>
>>> d1 = &a; /* where d1 and a are both of type int */
>>>
>>> specifies a conversion. Nothing in the C standard says or implies
>>> that. The types int and int* are not assignment-compatible, so
>>> the assignment is a constraint violation, requiring a diagnostic.
>>> *If* the compiler chooses to generate an executable after issuing
>>> the diagnostic, nothing in the C standard says anything about how
>>> it behaves. [...] a conforming implementation could do *anything*.
>>> [snip elaboration]

>>
>> I'm not sure what your reasoning is to reach this conclusion.
>> Certainly this assignment has a constraint violation, but you're
>> saying, in effect, that it has undefined behavior. Presumably
>> the underlying reasoning is one of two things, namely:
>>
>> A. There is a constraint violation, and any constraint
>> violation is necessarily undefined behavior; or
>>
>> B. The assignment statement is trying to assign a pointer
>> type to an integer type, and nothing in the Standard
>> says how to do that, so there is undefined behavior.
>>
>> IMO point A is incorrect, although I would agree the point
>> is debatable. Section 4 paragraph 3 says in part:
>>
>> If a ``shall'' or ``shall not'' requirement that appears
>> outside of a constraint or runtime-constraint is violated,
>> the behavior is undefined.

>
> IMHO A is correct (programs with constraint violations have
> undefined behavior), though I'm not sure I can prove it.
>
>> This statement makes it reasonable to infer that a constraint
>> violation might _not_ result in undefined behavior in some
>> instances, as otherwise there is no point in excluding it.
>> ("The exception proves the rule in cases not excepted.")

>
> Perhaps, but only if the behavior is actually defined somewhere.

The behavior is defined by the semantics paragraphs of "Simple
assignment", which the expression in question must have been
identified as being. (This point expanded on below.)

>> Turning to point B, I think it is clearly just wrong, because
>> of 6.5.16.1 p 2.

>
> Which says:
>
> In *simple assignment* (=), the value of the right operand is
> converted to the type of the assignment expression and
> replaces the value stored in the object designated by the left
> operand.
>
> That's an interesting point, but consider the definition of
> "constraint" in 3.8:
>
> restriction, either syntactic or semantic, by which the exposition
> of language elements is to be interpreted
>
> So the statement about the semantics of a simplea ssignment "is to
> be interpreted" in the context of the restriction on the operands.
> My conclusion from that is that if the constraint is violated,
> the statement doesn't apply.
>
> If the constraint is violated, it isn't a simple assignment.
> We don't know what it is, but it's not part of a valid C program.

The problem with this reasoning is that the compiler must have
identified the expression as a simple assignment, because the
constraint only applies to simple assignments, and violating a
constraint requires a diagnostic. If we don't know that the
expression is a simple assignment, then there is no constraint
violation, and the compiler would be free to treat the program as
having undefined behavior, without issuing a diagnostic. This is
a classic "you can't have it both ways" kind of situation. The
only reasonable way out is to say the compiler must identify the
expression in question as a simple assignment, and proceed
accordingly.

> A compiler is free to reject a program containing such an assignment.
> If it does so, the conversion described in 6.5.16.1p2 does not
> occur -- but that doesn't mean the compiler is non-conforming.

I don't see what this has to do with anything. Obviouly a
program that did not successfully compile (ie, was rejected)
won't have any of its semantic actions carried out. There are a
variety of reasons why a compiler might reject a program;
rejecting it because it has a constraint violation isn't any
different in this regard.

> I suppose you could (and apparently do) interpret it to mean that
> the conversion occurs *if* the program is not rejected. I find
> that interpretation a bit strained.

I don't see why. It seems reasonable that the semantics described
under "Simple assignment" would apply; detabable maybe, but not
unreasonable, certainly not a big stretch. And those semantics
clearly spell out a particular well-defined behavior (and which
includes the conversion).

>> Aside from the constraint violation, I don't see anything that
>> makes this assignment have undefined behavior. If it is true
>> that a constraint violation is not /ipso facto/ undefined
>> behavior, then the behavior of this assignment is well-defined.
>> A compiler is free to reject it (with the necessary diagnostic)
>> because of the constraint violation; but if the compiler chooses
>> to accept it, then the assignment must behave the same way that
>>
>> d1 = (int) &a;
>>
>> would.

>
> I disagree.

Let me point out that the final sentence is predicated on the 'If
it is true that ...' condition given earlier in the paragraph.
In this paragraph it is not my intention to make an absolute
statement, only a relative one.

To try to bring the conversation up a level: the essential point I
was trying to make is that the question is not black and white.
Reasonable people can disagree here. In the interest of giving a
fair presentation under such circumstances, I think it's better to
give a qualified statement rather than treating the matter as
completely settled.

> Note also that, quoting 4p6:
>
> A conforming implementation may have extensions [...] provided they
> do not alter the behavior of any strictly conforming program.
>
> which implies that such an extension *could* alter the behavior of a
> program containing such an assignment.
>
> (It could also imply that an extension could alter the behavior
> of printf("%d\n", INT_MAX), which I find a bit troubling. I'm not
> sure that strict conformance was the best criterion to use there.)

The area of "extensions" is a little murky. Looking through the
section on common extensions, it isn't clear just how much is
allowed (at least one example seems to imply that an extension
could change the meaning of a strictly conforming program).
Certainly extensions have great latitude to re-define behavior,
as your example illustrates, even if it isn't clear just how
great that latitude is.

However, regarding what is required for this kind of assignment
expression, the matter of extensions can easily be rendered moot,
because extensions are reguired to be documented. We can simply
ask the question of what behavior is required for implementations
that do not document any extensions in such cases.

Tim Rentsch, Apr 2, 2013
19. ### army1987Guest

On Sat, 30 Mar 2013 11:13:50 -0700, Tim Rentsch wrote:

> There is no guarantee that a pointer to any type other than void can be
> converted to any integer type other than _Bool. A pointer to void can
> be converted to the types intptr_t, but only if the implementation
> defines them, which the Standard does not require.

Is there any good reason why (intptr_t)&i isn't required to be the same
as (intptr_t)(void *)&i? (Crossposted to comp.std.c.)

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>

army1987, Apr 2, 2013
20. ### army1987Guest

Re: I have a doubt... (Was: difference between pointers)

On Mon, 01 Apr 2013 00:10:22 +0000, Kenny McCormack wrote:

> Which leads inevitably to the ago-old question. Say you find yourself
> in a situation where, speaking on the topic of dogs, large numbers of
> people call a tail a "leg". Do you accept that as acceptable usage and
> go along with the crowd, or do you patiently instruct them, over and
> over, that a tail is not a leg?
>
> And note, given that in this newsgroup, people never get tired of
> bitching about "void main" or telling people not to cast the return
> value of malloc, or about how not #includ'ing stdio.h causes undefined
> behavior, I don't think there's much likelihood they'll stop bitching
> about people misusing the word "doubt".

The difference being that there's an ISO standard defining what "void main
()" means or doesn't mean, but there's no official standard defining what
"doubt" means or doesn't mean; there are _de facto_ standards for that
but they don't happen to agree with each other. (I think it's most
useful to stick to one of the _de facto_ standards that are followed by a
sizeable number of native English speakers and don't confuse people
following different _de facto_ standards too much, and the particular _de
facto_ standard according to which "doubt" can mean 'question' doesn't
fulfil these criteria; but still.)

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>

army1987, Apr 2, 2013