Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

difference between pointers

226 views
Skip to first unread message

Varun Tewari

unread,
Mar 30, 2013, 11:36:42 AM3/30/13
to
hello all,

I get this doubt about this behavior of C.

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.

Why so when C doesn't really support operator overloading.

Eric Sosman

unread,
Mar 30, 2013, 12:04:33 PM3/30/13
to
The short (and technical, and not very helpful) answer is
that the code's behavior is undefined: The C language doesn't
specify what should happen, so *anything* might happen.

A longer answer ...

First, pointer arithmetic always operates in units of the
pointed-at type. Adding 1 to an `int*' advances the pointer
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
a `double' occupies eight, adding 1 advances the pointer by the
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).

Pointers are not "just addresses," but "addresses with type."

--
Eric Sosman
eso...@comcast-dot-net.invalid

BartC

unread,
Mar 30, 2013, 5:52:30 PM3/30/13
to


"Varun Tewari" <tewari...@gmail.com> wrote in message
news:15bf78d1-1712-420a...@googlegroups.com...
I don't understand what overloading has to do with it.

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

christian.bau

unread,
Mar 30, 2013, 6:51:40 PM3/30/13
to
On Mar 30, 3:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
> hello all,
>
> I get this doubt about this behavior of C.

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

> consider the following code.
>
> int a,b,d1,d2,diff;
>
> d1= &a;
> d2 = &b;

Both don't compile on my computer.

> diff = &a-&b;

This is undefined behaviour. The difference between two pointers is
only defined if both pointers point to the elements of the same array.
The difference between addresses of two unrelated variables is
undefined.

Tim Rentsch

unread,
Mar 30, 2013, 1:36:37 PM3/30/13
to
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

unread,
Mar 30, 2013, 2:13:50 PM3/30/13
to
Eric Sosman <eso...@comcast-dot-net.invalid> writes:

> On 3/30/2013 11:36 AM, Varun Tewari wrote:
>> hello all,
>>
>> I get this doubt about this behavior of C.
>>
>> 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.
>>
>> Why so when C doesn't really support operator overloading.
>
> The short (and technical, and not very helpful) answer is
> 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 [u]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 [u]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.

Keith Thompson

unread,
Mar 30, 2013, 4:40:52 PM3/30/13
to
Eric Sosman <eso...@comcast-dot-net.invalid> writes:
> On 3/30/2013 11:36 AM, Varun Tewari wrote:
>> I get this doubt about this behavior of C.
>>
>> 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) ks...@mib.org <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"

Tim Rentsch

unread,
Mar 30, 2013, 6:06:44 PM3/30/13
to
> 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.

Varun Tewari

unread,
Mar 31, 2013, 5:20:57 AM3/31/13
to
Yep it did give warning.Thnx for pointing the correct gcc option for correct ansi parsing.

Keith Thompson

unread,
Mar 31, 2013, 5:32:31 AM3/31/13
to
Tim Rentsch <t...@alumni.caltech.edu> writes:
> Keith Thompson <ks...@mib.org> 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.)

Joe Pfeiffer

unread,
Mar 31, 2013, 6:24:09 PM3/31/13
to
"christian.bau" <christ...@cbau.wanadoo.co.uk> writes:

> On Mar 30, 3:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
>> hello all,
>>
>> I get this doubt about this behavior of C.
>
> 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.

Kenny McCormack

unread,
Mar 31, 2013, 8:10:22 PM3/31/13
to
In article <1bzjxjc...@snowball.wb.pfeifferfamily.net>,
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!"

Joe Pfeiffer

unread,
Mar 31, 2013, 9:41:10 PM3/31/13
to
gaz...@shell.xmission.com (Kenny McCormack) writes:

> In article <1bzjxjc...@snowball.wb.pfeifferfamily.net>,
> Joe Pfeiffer <pfei...@cs.nmsu.edu> wrote:
>>"christian.bau" <christ...@cbau.wanadoo.co.uk> writes:
>>
>>> On Mar 30, 3:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
>>>> hello all,
>>>>
>>>> I get this doubt about this behavior of C.
>>>
>>> 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.

Keith Thompson

unread,
Mar 31, 2013, 11:29:14 PM3/31/13
to
"BartC" <b...@freeuk.com> writes:
> "Varun Tewari" <tewari...@gmail.com> wrote in message
> news:15bf78d1-1712-420a...@googlegroups.com...
>> I get this doubt about this behavior of C.
>>
>> 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.
>>
>> Why so when C doesn't really support operator overloading.
>
> I don't understand what overloading has to do with it.

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

> 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.

Øyvind Røtvold

unread,
Apr 1, 2013, 1:30:22 AM4/1/13
to

gaz...@shell.xmission.com (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.

Kenny McCormack

unread,
Apr 1, 2013, 10:55:21 AM4/1/13
to
In article <v6ohajq...@jjj.jjj>,
�yvind R�tvold <orot...@gmail.com> wrote:
>
>gaz...@shell.xmission.com (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.

Varun Tewari

unread,
Apr 1, 2013, 1:31:11 PM4/1/13
to
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.

:)

Tim Rentsch

unread,
Apr 2, 2013, 12:09:10 AM4/2/13
to
Varun Tewari <tewari...@gmail.com> 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

unread,
Apr 2, 2013, 1:41:19 AM4/2/13
to
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.

army1987

unread,
Apr 2, 2013, 10:48:43 AM4/2/13
to
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 [u]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

unread,
Apr 2, 2013, 11:02:45 AM4/2/13
to
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.)

Keith Thompson

unread,
Apr 2, 2013, 11:46:47 AM4/2/13
to
Well, yes, but more on that below.
I went a little overboard saying that it isn't a simple assignment.
Syntactically, it clearly is.

But once the compiler recognizes it as a simple assignment, how
far must it "proceed accordingly"?

Semantically, it violates a constraint. A constraint is by
definition a "restriction, either syntactic or semantic, by which
the exposition of language elements is to be interpreted". I admit
that's a bit vague, but what I get from that is that violating
a constraint invalidates the exposition. My reading of 6.5.16.1
is roughly "*If* the following constraints are satisified *then* a
simple assignment has the following semantics." That's not the only
possible reading, of course, but it's the only one I can think of
that causes the definition of "constraint" to make sense.

And it turns out I've asked about this in comp.std.c several times
over the years (apparently I've been posting here long enough that
I sometimes forget things I've discussed before):

https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/WNVXRSCqrGU
https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/3Nu8-vlJOEU
https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/M2UxT1wk1xQ

The threads are interesting reading if you're into that kind of thing.
Several people strongly stated their opinion that program that violate
constraints have undefined behavior, but I wasn't convinced that any of
them proved it.

One relevant post from 2007 (note that Doug Gwyn is a member of the
Committee):

https://groups.google.com/group/comp.std.c/msg/4661905eda66827?dmode=source&output=gplain&noredirect

"Douglas A. Gwyn" <DAG...@null.net> writes:
[...]
> Issuance of a "diagnostic" (meeting the implementation definition for
> identification, required for conformance to the C standard) implies
> rejection of the program (again, insofar as conformance is concerned).
> If an implementation wants to proceed to do something further with
> the translation unit, typically to continue processing to potentially
> generate additional diagnostics but also to go ahead and produce
> object code, then that is its business and it is allowed to do so.

I like that interpretation, and I wish it were clearly stated in the
standard.

I think the bottom line is that the standard is unclear about
the semantics, if any, of programs that violate constraints, and
particularly about the definition of "constraint". A clear statement
in the standard (even in a note) that any program that violates a
constraint, if it's accepted, has undefined behavior would settle
the issue. A clear statement of the opposite would do so as well.

*If* my interpretation is correct, then the cases where a description
of the semantics applies even when a constraint is violated (as in
the definition of simple assignment) can be explained as avoiding
redundancy. Yes the semantics section under "Simple assignment"
says that the RHS is converted to the type of the LHS; it doesn't
say *again* that the type must meet the constraints because that's
already been stated.

It seems odd to me to permit a compiler to reject a given construct,
but to impose specific requirements on its behavior if it's accepted.
A programmer cannotr reasonably depend on such a guarantee. On the
other hand, there are plenty of things in the standard that I find
odd, so that doesn't prove anything.

[SNIP]

> 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.

I believe we've demonstrated that by being reasonable people
disagreeing about it. 8-)}

> 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.

Hmm. Feel free to assume that anything posted under my name is prefixed
with "In my opinion, ".

[snip]

Nick Bowler

unread,
Apr 2, 2013, 1:30:15 PM4/2/13
to
On Tue, 02 Apr 2013 14:48:43 +0000, army1987 wrote:
> 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 [u]intptr_t, but only if the implementation
>> defines them, which the Standard does not require.

This is not quite correct. Any pointer type can be converted to any
integer type. In most cases, however, the result is implementation-
defined.

> 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.)

The literal text of the standard only requires the conversion to
(u)intptr_t and back again to work for "any valid pointer to void".
As there is a similar requirement for conversions of other kinds of
object pointers to void * and back again, I can't think of a good
reason for why there is no requirement for conversion of other sorts of
object pointers to (u)intptr_t and back again to work.

If I encountered an implementation which provides (u)intptr_t but
conversions of non-void object pointers and back again did not work, I
would assume that this was either the result of malice on the part of the
implementators, or maybe they just ported some code from the DeathStation
9000.

Fortunately, in this situation the craziness would have to be documented
as the result is squarely in implementation-defined territory.

Tim Rentsch

unread,
Apr 2, 2013, 2:57:10 PM4/2/13
to
army1987 <army...@ask-for-it.invalid> writes:

> 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 [u]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.)

The pointer types (int *) and (void *) don't necessarily have
the same representation, or even the same size. The most
natural way of effecting a pointer-to-integer conversion is
just to copy the bits of the pointer into the bits of the
integer object representation. Obviously if we start with
a different representation, or even worse a different size,
that could affect the results.

Tim Rentsch

unread,
Apr 2, 2013, 3:11:38 PM4/2/13
to
Nick Bowler <nbo...@draconx.ca> writes:

> On Tue, 02 Apr 2013 14:48:43 +0000, army1987 wrote:
>> 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 [u]intptr_t, but only if the implementation
>>> defines them, which the Standard does not require.
>
> This is not quite correct. Any pointer type can be converted to any
> integer type. In most cases, however, the result is implementation-
> defined.

Let me clarify my earlier statement. There is no guarantee that
a pointer can be _definedly_ converted to any integer type other
than _Bool. The Standard allows any pointer type to be converted
to any integer type, but if the result cannot be represented in
the target type then the behavior is undefined, and the Standard
says specifically that the result of such a conversion (other
than to _Bool) "need not be in the range of values of any integer
type."

Tim Rentsch

unread,
Apr 2, 2013, 4:17:43 PM4/2/13
to
My reading is that it places limits on what must be accepted by
the compiler but doesn't otherwise change the applicable semantic
descriptions. This shouldn't be a strange idea, as after all it
is what people expect for environmental limits -- the compiler
may reject any program that exceeds an environmental limit, but
if the program is accepted then the compiler better follow the
given semantic descriptions. I think the difference is primarily
one of expectation -- we expect a constraint violation will
result in a program being rejected, whereas we hardly ever expect
a program will be rejected because an environmental limit was
exceeded (and certainly the hope is that the program will not be
rejected!).

> And it turns out I've asked about this in comp.std.c several times
> over the years (apparently I've been posting here long enough that
> I sometimes forget things I've discussed before):
>
> https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/WNVXRSCqrGU
> https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/3Nu8-vlJOEU
> https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/M2UxT1wk1xQ
>
> The threads are interesting reading if you're into that kind of thing.
> Several people strongly stated their opinion that program that violate
> constraints have undefined behavior, but I wasn't convinced that any of
> them proved it.

I expect there is some interesting reading there. I would be
more enthusiastic if the "improved" Google groups interface
weren't so abysmally bad. :(

> One relevant post from 2007 (note that Doug Gwyn is a member of the
> Committee):
>
> https://groups.google.com/group/comp.std.c/msg/4661905eda66827?dmode=source&output=gplain&noredirect
>
> "Douglas A. Gwyn" <DAG...@null.net> writes:
> [...]
> > Issuance of a "diagnostic" (meeting the implementation definition for
> > identification, required for conformance to the C standard) implies
> > rejection of the program (again, insofar as conformance is concerned).
> > If an implementation wants to proceed to do something further with
> > the translation unit, typically to continue processing to potentially
> > generate additional diagnostics but also to go ahead and produce
> > object code, then that is its business and it is allowed to do so.
>
> I like that interpretation, and I wish it were clearly stated in the
> standard.

Note that the long paragraph doesn't say one way or the other as
to whether the proceeding compilation is obliged to honor other
semantic descriptions that are well-defined. The author may have
a position on the subject, but I don't think this paragraph
clearly expresses it.

> I think the bottom line is that the standard is unclear about
> the semantics, if any, of programs that violate constraints, and
> particularly about the definition of "constraint". A clear statement
> in the standard (even in a note) that any program that violates a
> constraint, if it's accepted, has undefined behavior would settle
> the issue. A clear statement of the opposite would do so as well.

I agree 100%.

> *If* my interpretation is correct, then the cases where a description
> of the semantics applies even when a constraint is violated (as in
> the definition of simple assignment) can be explained as avoiding
> redundancy. Yes the semantics section under "Simple assignment"
> says that the RHS is converted to the type of the LHS; it doesn't
> say *again* that the type must meet the constraints because that's
> already been stated.
>
> It seems odd to me to permit a compiler to reject a given construct,
> but to impose specific requirements on its behavior if it's accepted.
> A programmer cannotr reasonably depend on such a guarantee. On the
> other hand, there are plenty of things in the standard that I find
> odd, so that doesn't prove anything.

It doesn't seem so odd to me because there are at least two other
cases where the Standard does just that, those being exceeding an
environment limit and use of a conditionally present feature (of
which C11 has too many IMO, but that is a separate discussion).

> [SNIP]
>
>> 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.
>
> I believe we've demonstrated that by being reasonable people
> disagreeing about it. 8-)}

Just so. :)

>> 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.
>
> Hmm. Feel free to assume that anything posted under my name is prefixed
> with "In my opinion, ".

There are two reasons why I hope you'll reconsider this response.

First, I don't think it's really an accurate description all the
time. Some of the things you say you consider (I believe) to be
simply indisputable, ie, that no reasonable (and informed) person
would disagree. For example, the printf() statement you mentioned
earlier as not being strictly conforming -- this is not just an
opinion, as it cannot be reasonably disputed. It is valuable to
distinguish these two kinds of situations.

Second, and probably more important, I'm not the only audience for
your comments. Lots of people read what you have to say, and it
helps them understand not just the language but also the culture
of people who are interested in the language definition, and how
firm or weak the consensus is in different areas. IMO you would
be doing them a disservice to voice statements of opnion as if
they are statements of fact, or to not distinguish between cases
where you are giving a statement of opinion and where you feel
there is overwhelming consensus on a particular issue. By all
means, in any case where you feel there is overwhelming consensus,
please go ahead and respond unequivocally. In other cases,
however, where there is not such a strong consensus, and you
think reasonable people can disagree, I hope you'll agree that
it is better to express such remarks in a qualified way, so
readers get a more rounded view of the discussional landscape.

Jorgen Grahn

unread,
Apr 2, 2013, 4:20:08 PM4/2/13
to
On Tue, 2013-04-02, Tim Rentsch wrote:
> Varun Tewari <tewari...@gmail.com> 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
...
> gcc -std=c11 -pedantic-errors

I strongly recommend

-std=something -Wall -Wextra -pedantic -O2

It's a good start for new code: a warning level that is high, but not
so high that you have to make your code less readable to please the
compiler.

I also recommend reading the compiler manual, to get familiar with the
different options.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

unread,
Apr 2, 2013, 7:24:21 PM4/2/13
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
> On Tue, 2013-04-02, Tim Rentsch wrote:
>> Varun Tewari <tewari...@gmail.com> 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
> ...
>> gcc -std=c11 -pedantic-errors
>
> I strongly recommend
>
> -std=something -Wall -Wextra -pedantic -O2

Why -O2 rather than -O3?

> It's a good start for new code: a warning level that is high, but not
> so high that you have to make your code less readable to please the
> compiler.
>
> I also recommend reading the compiler manual, to get familiar with the
> different options.

Les Cargill

unread,
Apr 2, 2013, 7:44:34 PM4/2/13
to
Keith Thompson wrote:
> Jorgen Grahn <grahn...@snipabacken.se> writes:
>> On Tue, 2013-04-02, Tim Rentsch wrote:
>>> Varun Tewari <tewari...@gmail.com> 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
>> ...
>>> gcc -std=c11 -pedantic-errors
>>
>> I strongly recommend
>>
>> -std=something -Wall -Wextra -pedantic -O2
>
> Why -O2 rather than -O3?
>

Ozone is a pollutant?

>> It's a good start for new code: a warning level that is high, but not
>> so high that you have to make your code less readable to please the
>> compiler.
>>
>> I also recommend reading the compiler manual, to get familiar with the
>> different options.
>


--
Les Cargill

Jorgen Grahn

unread,
Apr 3, 2013, 6:20:03 AM4/3/13
to
On Tue, 2013-04-02, Keith Thompson wrote:
> Jorgen Grahn <grahn...@snipabacken.se> writes:
>> On Tue, 2013-04-02, Tim Rentsch wrote:
>>> Varun Tewari <tewari...@gmail.com> 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
>> ...
>>> gcc -std=c11 -pedantic-errors
>>
>> I strongly recommend
>>
>> -std=something -Wall -Wextra -pedantic -O2
>
> Why -O2 rather than -O3?

I included the optimization option because at least historically you
could get more warnings about dead code/data that way.

I could have written -Os or -O3, but some sources say the higher
levels may produce worse code due to too aggressive inlining etc, and
that you should measure before applying them (if performance is
important on that level).

Nick Keighley

unread,
Apr 3, 2013, 8:20:54 AM4/3/13
to
On Mar 30, 4:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
> hello all,
>
> I get this doubt about this behavior of C.
>
> 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.
>
> Why so when C doesn't really support operator overloading.


what compiler successfully compiles this code?

Nick Keighley

unread,
Apr 3, 2013, 8:22:50 AM4/3/13
to
:)

Keith Thompson

unread,
Apr 3, 2013, 1:17:04 PM4/3/13
to
gcc does, once you add the obvious boilerplate.

It "successfully" compiles it in the sense that it generates an
executable that actually prints something. It does produce the required
diagnostics, but they're merely warnings. (The "-pedantic-errors"
option makes them fatal errors.)

Tim Rentsch

unread,
Apr 11, 2013, 6:48:31 PM4/11/13
to
Jorgen Grahn <grahn...@snipabacken.se> writes:

> On Tue, 2013-04-02, Tim Rentsch wrote:
>> Varun Tewari <tewari...@gmail.com> 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
> ...
>> gcc -std=c11 -pedantic-errors
>
> I strongly recommend
>
> -std=something -Wall -Wextra -pedantic -O2
>
> [snip elaboration]

I used to be a fan of -Wall and -W (aka -Wextra). Now,
not so much. In no particular order, my complaints are:

* I believe good programming practice normally treats
warnings as errors (ie, -Werror in gcc). Using -Wall
or -Wextra sometimes works at cross-purposes to that.

* The set of warnings included in -Wall or -Wextra include
some that are purely stylistic and have no bearing on
code correctness.

* IMO some of the style warnings are not just neutral but
actually bad.

* Some -Wall/-Wextra warning conditions can be removed
selectively with other option settings, but some can't.

* In cases where a warning class indicates a potential
code problem, there often are too many false positives.
This has the effect of training people either to muck
their code about just to shut up the compiler, or to
ignore warnings; neither of these is a good thing.

* The documentation is wrong, at least in the sense of
being incomplete -- there are warnings that come out
under -Wall or -Wextra that don't correspond to any
of the described warning conditions (and hence there
is no way to turn them off, at least not that I could
find).

* Moving target - the set of warnings included under -Wall
or -Wextra in one version of gcc might change in the next
version of gcc. It is very disconcerting to find code
thought to be completely clean suddenly start generating
warnings when compiled in a new environment.

There are lots of individual warnings in gcc that are quite
valuable, eg, "variable might not be initialized before use."
But rather than using the -Wall/-Wextra shotgun to turn
everything on, it's better to turn the high quality warning
conditions on individually, and not use the others. And also
-Werror, or at least -pedantic-errors (and please let the GNU
people know when -pedantic-errors gives an error for something
that is only undefined behavior, and not a syntax/constraint
violation).

Tim Rentsch

unread,
Apr 11, 2013, 6:52:29 PM4/11/13
to
Jorgen Grahn <grahn...@snipabacken.se> writes:

> On Tue, 2013-04-02, Tim Rentsch wrote:
>> Varun Tewari <tewari...@gmail.com> 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
> ...
>> gcc -std=c11 -pedantic-errors
>
> I strongly recommend
>
> -std=something -Wall -Wextra -pedantic -O2
>
> [...]

Another complaint I forgot:

* Usually turning on optimization (eg, -O2) will allow
additional warning conditions to be checked, but it
also can have the effect of removing some warnings
that are generated without it.

glen herrmannsfeldt

unread,
Apr 11, 2013, 7:23:24 PM4/11/13
to
Tim Rentsch <t...@alumni.caltech.edu> wrote:

(snip of things I already agree with)

> * In cases where a warning class indicates a potential
> code problem, there often are too many false positives.
> This has the effect of training people either to muck
> their code about just to shut up the compiler, or to
> ignore warnings; neither of these is a good thing.

Yes. People often consider the benefit of adding a warning,
but not its cost. Looking through false positives is a
definite cost.

> * The documentation is wrong, at least in the sense of
> being incomplete -- there are warnings that come out
> under -Wall or -Wextra that don't correspond to any
> of the described warning conditions (and hence there
> is no way to turn them off, at least not that I could
> find).

> * Moving target - the set of warnings included under -Wall
> or -Wextra in one version of gcc might change in the next
> version of gcc. It is very disconcerting to find code
> thought to be completely clean suddenly start generating
> warnings when compiled in a new environment.

I suppose that could be fixed with a warning version option,
not to generate warnings added since a specific version of
the compiler. Not likely to be added, though.

> There are lots of individual warnings in gcc that are quite
> valuable, eg, "variable might not be initialized before use."

I somewhat like the Java idea on this. Any variable that the
compiler can't detect is initialized before use is an error.

Sometimes the compiler doesn't see something that you know,
but reasonably often it is right.

> But rather than using the -Wall/-Wextra shotgun to turn
> everything on, it's better to turn the high quality warning
> conditions on individually, and not use the others. And also
> -Werror, or at least -pedantic-errors (and please let the GNU
> people know when -pedantic-errors gives an error for something
> that is only undefined behavior, and not a syntax/constraint
> violation).

I suppose those could be selected separately if one wanted them.

-- glen

Tim Rentsch

unread,
Apr 11, 2013, 8:54:13 PM4/11/13
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:

> Tim Rentsch <t...@alumni.caltech.edu> wrote:
> [snip]
>> There are lots of individual warnings in gcc that are quite
>> valuable, eg, "variable might not be initialized before use."
>
> I somewhat like the Java idea on this. Any variable that the
> compiler can't detect is initialized before use is an error.

Java pays a price for this choice, namely, the algorithm for
deciding whether a variable has been initialized therefore
must be included as part of the language definition. (And
whatever algorithm is chosen, it can't be right all the time,
because the problem is undecidable.) That choice may be a
good choice for Java, but IMO it would be a bad one for C.

glen herrmannsfeldt

unread,
Apr 11, 2013, 9:20:52 PM4/11/13
to
Tim Rentsch <t...@alumni.caltech.edu> wrote:
> glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:

>> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> [snip]
>>> There are lots of individual warnings in gcc that are quite
>>> valuable, eg, "variable might not be initialized before use."

>> I somewhat like the Java idea on this. Any variable that the
>> compiler can't detect is initialized before use is an error.

> Java pays a price for this choice, namely, the algorithm for
> deciding whether a variable has been initialized therefore
> must be included as part of the language definition. (And
> whatever algorithm is chosen, it can't be right all the time,
> because the problem is undecidable.)

I have wondered about that. Seems that you might get away
with improving the algorithm, such that old programs would
still compile. New ones might not compile on old compilers,
but then they might not anyway if they use new features.

But as for the undecidable, the default is that it is
an error. That is, if the compiler can't prove that it is
defined before use, it is an error.

That is only for scalar variables. Arrays are always initialized
to zero when allocated.

> That choice may be a good choice for Java, but IMO
> it would be a bad one for C.

I agree.

(Besides, it is a little late now.)

-- glen

Jorgen Grahn

unread,
Apr 12, 2013, 9:35:52 AM4/12/13
to
On Thu, 2013-04-11, Tim Rentsch wrote:
> Jorgen Grahn <grahn...@snipabacken.se> writes:
>
>> On Tue, 2013-04-02, Tim Rentsch wrote:
>>> Varun Tewari <tewari...@gmail.com> 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
>> ...
>>> gcc -std=c11 -pedantic-errors
>>
>> I strongly recommend
>>
>> -std=something -Wall -Wextra -pedantic -O2
>>
>> [snip elaboration]

This part of the elaboration is important:

>> It's a good start for new code [...]

I didn't intend to suggest the flags above as the universal solution
to all problems.

Tim Rentsch

unread,
Apr 13, 2013, 2:39:00 PM4/13/13
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:

> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> glen herrmannsfeldt <g...@ugcs.caltech.edu> writes:
>
>>> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>>> [snip]
>>>> There are lots of individual warnings in gcc that are quite
>>>> valuable, eg, "variable might not be initialized before use."
>>>
>>> I somewhat like the Java idea on this. Any variable that the
>>> compiler can't detect is initialized before use is an error.
>>
>> Java pays a price for this choice, namely, the algorithm for
>> deciding whether a variable has been initialized therefore
>> must be included as part of the language definition. (And
>> whatever algorithm is chosen, it can't be right all the time,
>> because the problem is undecidable.)
>
> I have wondered about that. Seems that you might get away
> with improving the algorithm, such that old programs would
> still compile. New ones might not compile on old compilers,
> but then they might not anyway if they use new features.

A new language definition could choose a different algorithm, or
specify an initialization rule for all declared variables, or
allow uninitialized variables, or some combination of the above.
But compilers have to do what the language definition says, for
whatever language they are implementing.

> But as for the undecidable, the default is that it is
> an error.

What you mean is that the language definition for Java has
chosen a conservative algorithm that never mis-identifies an
uninitialized variable as having been initialized. And I
believe that's right.

> That is, if the compiler can't prove that it is defined
> before use, it is an error.

The compiler is obliged to do whatever the language definition
says, which completely defines the result, with no latitude
left to the compiler. Anything else is not consistent with
the "Write once, run anywhere" philosophy that Java espouses.

Tim Rentsch

unread,
Apr 13, 2013, 3:23:44 PM4/13/13
to
Jorgen Grahn <grahn...@snipabacken.se> writes:

> On Thu, 2013-04-11, Tim Rentsch wrote:
>> Jorgen Grahn <grahn...@snipabacken.se> writes:
>>
>>> On Tue, 2013-04-02, Tim Rentsch wrote:
>>>> Varun Tewari <tewari...@gmail.com> 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
>>> ...
>>>> gcc -std=c11 -pedantic-errors
>>>
>>> I strongly recommend
>>>
>>> -std=something -Wall -Wextra -pedantic -O2
>>>
>>> [snip elaboration]
>
> This part of the elaboration is important:
>
>>> It's a good start for new code [...]

Yes, my snipping here was a bit overzealous. Sorry about that.

However, that qualifier doesn't lessen my reaction -- if anything
it intensifies it. Using -Wall and -Wextra on new code is the
worst place to use them, because that's where they are most
likely to nudge people into bad habits, or cause problems later.
It is much better to use -Wall/-Wextra sparingly, on source code
that is more mature, as an independent sanity check or quality
assessment step. Using -Wall or -Wextra on a regular basis,
especially as a default for new code, is IMO a bad practice and
one likely to lead to poor coding habits.

> I didn't intend to suggest the flags above as the universal
> solution to all problems.

Certainly that was not my impression, and I hope my comments
didn't suggest otherwise.

Jorgen Grahn

unread,
Apr 13, 2013, 5:01:55 PM4/13/13
to
Ok, good. But we're still on opposide sides: IMO -Wall, -Wextra and
-pedantic lead to *good* habits in the usual case.

(There's one class of warnings I would agree are problematic, and
that's the ones for unused static functions, parameters and variables.
Useful, but when they don't alert you to an actual bug, it's often
hard to do anything about them without making the code worse. And yes,
I refuse to do that just to please the compiler.)

Others will have to make up their own minds, I guess.

Noob

unread,
Apr 13, 2013, 6:38:08 PM4/13/13
to
Tim Rentsch wrote:

> Usually turning on optimization (eg, -O2) will allow
> additional warning conditions to be checked, but it
> also can have the effect of removing some warnings
> that are generated without it.

Do you have an example?

Tim Rentsch

unread,
Apr 18, 2013, 7:41:05 PM4/18/13
to
Unfortunately all I have is a memory of seeing it
happen, not a specific example. Probably something
related to -Wsign-compare, but I'm not sure of that.

Seebs

unread,
Apr 19, 2013, 12:13:40 AM4/19/13
to
On 2013-03-31, Joe Pfeiffer <pfei...@cs.nmsu.edu> wrote:
> "christian.bau" <christ...@cbau.wanadoo.co.uk> writes:
>
>> On Mar 30, 3:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
>>> hello all,
>>>
>>> I get this doubt about this behavior of C.
>>
>> 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.

After thinking about this for a long time, I've concluded that it's worth
pointing out the confusion to people, because there are a lot of
circumstances in which substituting "doubt" for "question" has a significant
chance of insulting people. Replacing "I don't understand that" with "I think
you are lying to me" is not a harmless change.

-s
--
Copyright 2013, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Joe Pfeiffer

unread,
Apr 19, 2013, 12:53:36 AM4/19/13
to
Seebs <usenet...@seebs.net> writes:

> On 2013-03-31, Joe Pfeiffer <pfei...@cs.nmsu.edu> wrote:
>> "christian.bau" <christ...@cbau.wanadoo.co.uk> writes:
>>
>>> On Mar 30, 3:36 pm, Varun Tewari <tewari.va...@gmail.com> wrote:
>>>> hello all,
>>>>
>>>> I get this doubt about this behavior of C.
>>>
>>> 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.
>
> After thinking about this for a long time, I've concluded that it's worth
> pointing out the confusion to people, because there are a lot of
> circumstances in which substituting "doubt" for "question" has a significant
> chance of insulting people. Replacing "I don't understand that" with "I think
> you are lying to me" is not a harmless change.

It's an example of being strict in what you say, and loose in what you
read. When you write and you're pretty sure the person you're
responding to is a clueless moron, you should say "I don't understand
what you said". When you read somebody who says "you're a clueless
moron", you should interpret that as the person not understanding what
you said.

Tim Rentsch

unread,
Apr 20, 2013, 4:23:11 PM4/20/13
to
Probably some of these are simply differences of opinion on
certain style choices. In most cases though I think it reflects
a different attitude of warnings versus errors, or tolerance for
"unimportant" warnings. IME it really helps code quality to
treat warnings as errors. Unfortunately that breaks down if the
conditions being tested generate too many false positives, which
the -Wall/-Wextra messages often do. What's more, often these
false positives happen in cases where there really isn't any way
to repair them gracefully, because they arise as a result of
macro expansion. This type of situation is difficult to deal
with if one also uses -Werror, which IMO it almost always should.

> (There's one class of warnings I would agree are problematic,
> and that's the ones for unused static functions, parameters and
> variables. Useful, but when they don't alert you to an actual
> bug, it's often hard to do anything about them without making
> the code worse. And yes, I refuse to do that just to please
> the compiler.)

Related to this is the problem of what/when warnings are
generated changing over time. Reminds me of the "life
is like a box of chocolates" quote -- with -Wall/-Wextra,
you never know what you're gonna get.

> Others will have to make up their own minds, I guess.

You have said what you think but you haven't really gone into why
you think it (and I note the exception above, for unused things).
It would help the discussion if you could try explaining the
reasoning underlying other individual error conditions, and also
other areas of -Wall/-Wextra in general (as opposed to individual
conditions), like the ones I talked about in my earlier message.

Phil Carmody

unread,
May 26, 2013, 1:46:43 PM5/26/13
to
Like Tim, I'm not 100% sure, but I'm 90% sure I've seen the
compiler warn about variables being assigned to and then never
subsequently read at higher optimisation levels. As higher O
levels attempt to cut corners, any time a corner is cut which
makes some of your source code redundant, you can expect, or
at least hope for, a diagnostic.

Phil
--
"In a world of magnets and miracles"
-- Insane Clown Posse, Miracles, 2009. Much derided.
"Magnets, how do they work"
-- Pink Floyd, High Hopes, 1994. Lauded as lyrical geniuses.
0 new messages