Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #128019

Re: lvalue types

From Keith Thompson <kst-u@mib.org>
Newsgroups comp.lang.c
Subject Re: lvalue types
Date 2018-03-19 11:52 -0700
Organization None to speak of
Message-ID <lnin9rrj8u.fsf@kst-u.example.com> (permalink)
References (2 earlier) <kfn7eqtsfgk.fsf@x-alumni2.alumni.caltech.edu> <lnefl0g9gs.fsf@kst-u.example.com> <kfnh8pwqgwn.fsf@x-alumni2.alumni.caltech.edu> <lna7vnft8l.fsf@kst-u.example.com> <kfnin9snh05.fsf@x-alumni2.alumni.caltech.edu>

Show all headers | View raw


Tim Rentsch <txr@alumni.caltech.edu> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>> Keith Thompson <kst-u@mib.org> writes:
>>>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>>>> Keith Thompson <kst-u@mib.org> writes:
>>>>>> [When using . or ->, what is "accessed"?]
>>>>>> Let me make the point more succinctly.
>>>>>>
>>>>>>     struct s { int m; };
>>>>>>     struct s obj;
>>>>>>     obj.m = 42;
>>>>>>
>>>>>> obj.m is an lvalue of type int.  The assignment accesses
>>>>>> (specifically modifies) the object obj.m, which is of type int;
>>>>>> that's perfectly fine under 6.5p7.  It also accesses (i.e.,
>>>>>> modifies) the object obj, which is of type struct s.
>>>>>
>>>>> I don't subscribe to this view, more specifically the last
>>>>> sentence.  Consider a union rather than a struct:
>>>>
>>>> [snip]
>>>>
>>>> Let's consider the original struct.
>>>>
>>>> N1570 3.1 defines "access" as
>>>>
>>>>     <execution-time action> to read or modify the value of an object
>>>>
>>>> Wouldn't you agree that `obj.m = 42;` modifies the value of obj?
>>>
>>> I would say no.  It does change some, or in this particular case
>>> maybe all, of the bytes that hold the object representation of
>>> obj, but that's not the same thing.
>>
>> I truly do not understand what you're saying here.
>>
>> Consider this program:
>>
>> #include <stdio.h>
>> int main(void) {
>>     struct s { int m; };
>>     struct s obj = { 0 };
>>     printf("obj.m = %d\n", obj.m);
>>     obj.m = 42;
>>     printf("obj.m = %d\n", obj.m);
>> }
>>
>> The output is:
>>
>> obj.m = 0
>> obj.m = 42
>>
>> Assume, for simplicity, that struct s has no padding bytes
>> (sizeof (struct s) == sizeof (int)) and int has no padding
>> bits (the latter probably doesn't matter).
>>
>> Before the assignment, obj has one value.  After the assignment,
>> obj has a different value.  The value changed because of the
>> assignment.
>>
>> To "access" is, by definition, "to read or modify the value of an
>> object".
>>
>> And you're saying that that assignment, which caused the value of
>> obj to change, did not modify the value of obj?
>>
>> Are you using a different meaning than I am for some seemingly
>> straighforward word?  (value?  object?  modify?)
>
> I suspect the key difference is you assume the Standard uses
> language in a precise and rigorous way (at least I am guessing
> you assume that), and I don't.  Take for example the word
> "value".  Strictly speaking, values aren't stored in objects.
> What is stored is some representation (not guaranteed to be
> unique) for the value.  Sometimes the Standard recognizes this
> distinction, and sometimes it doesn't.

I assume that the Standard at least attempts to use language precisely.
Since it's written in English, it can't do that with 100% reliability.
(I think there have been attempts to define C using a more formal
notation, but even if successful such a definition might not be useful
to implementers and/or users.)

I know that the Standard is imprecise in places.

> Another example is "object".  The term "object" is defined as a
> region of storage (in the execution environment, plus some other
> stuff that doesn't matter for present purposes).  Yet, in 6.2.4,
> discussing object lifetimes, there is this statement:
>
>     If the block is entered recursively, a new instance of the
>     object is created each time.
>
> But this is absurd.  If a block is entered recursively, we don't
> make a new instance of a certain region of storage.  Rather what
> happens is we allocate a different, unrelated region of storage.
> In the quoted sentence the word "object" is being used in a way
> that belies its definition.  And it is used in other, different
> ways in other places.

Sure, I see what you mean.  I think the intent is clear enough,
though.  It might be possible to change either the definition
of "object" or the description of what happens when a block is
entered recursively.  I haven't taken the time to think through
what would be required, and I don't necessarily suggest that it
would be worthwhile.

But your vague statement about how precise the Standard's wording is
or isn't does not, as far as I can tell, begin to answer my question.

Given that the Standard's wording is often imprecise, we have to fall
back to common sense, interpreting words as we might in everday written
English.

Given:

    struct s { int m; };
    struct s obj = { 0 };
    obj.m = 42;

(I've added an initializer to guarantee that the value actually
changes), I cannot think of any interpretation of the wording or intent
of the standard, precise or imprecise, that would lead to the conclusion
that the assignment modifies obj.m but does not modify obj.

obj.m has a value before the assignment.  It has a different value
after the assignment.  obj has a value before the assignment.
It has a different value after the assignment.

If you're saying that the assignment does not modify the value of obj,
how did you reach that conclusion?  If you're saying that the standard
doesn't say whether the assignment modifies the value of obj or not, how
did you reach that conclusion?

I don't think you mean to say that the standard is imprecise, therefore
you can reach any conclusion you like.

The definition of "access" is "to read or modify the value of an
object".  We can nitpick the imprecise ways the Standard uses the terms
"value" and "object", but I don't see that that leads us anywhere
useful.


[...]

>>> Instead of being used in an assignment, suppose we have obj.m
>>> being used to get the value of member m.
>>
>> No, let's concentrate for now on the assignment.
>
> This reaction sounds like confirmation bias - focusing on cases
> that support your theory, and disregarding cases that may be in
> conflict with it.

No, I'm simply trying to understand your take on an example that seems
straightforward to me.  Certainly any interpretation of the Standard
should apply to all cases -- which means that your interpretation should
apply to the assignment.  If you can explain that, I'll be willing to
move on to other examples.

> with everything the Standard says, not just with parts of it.  In
> particular the Standard is not like a logical system or a math
> textbook - if a chain of logic based on one passage leads to a
> contradiction with some other passage, there's a good chance that
> how the first passage was interpreted is wrong.  So I think it's
> important to look at other cases, such as the one mentioned,
> before reaching a definite conclusion.
>
>>>> Are you saying that
>>>>     obj.m = 42;
>>>> only modifies obj.m, but
>>>>     obj = (struct s){.obj = 42};
>>>> (which has an equivalent effect) modifies both obj and obj.m?
>>>
>>> It isn't quite right to say the two assignments have equivalent
>>> effect.  The effects are allowed to be equivalent, but they are
>>> not guaranteed to be equivalent.  (In fact I believe there are
>>> compilers for which the effects are different, and deliberately
>>> so, if not for this exact case then for similar ones.)
>>
>> Can you provide a concrete example?  If you're talking about
>> padding bytes, then sure, there can be a difference.  Does your
>> statement apply only when there are padding bytes?  (I note that
>> the particular struct type I used in the example is very unlikely
>> to have padding bytes.)
>
> What you are saying, in effect, is that the results may be
> equivalent in some implementations.  And that's true, they may
> be.  My point is that they are not guaranteed to be equivalent in
> all implementations.  This is similar to my last comment - for a
> theory to be right it has to be right in all possible situations,
> not just a few convenient situations.  That is important when
> what we are doing (as we are doing here) is trying to evaluate a
> theory about what the Standard means.

Is there some reason you're not answering my questions?  If I ask
you a question, it's because I think your answer will help me to
understand what you're talking about.

Can you provide a concrete example where the two assignments do
not have identical effects?  Are you talking about padding bytes?

-- 
Keith Thompson (The_Other_Keith) kst-u@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"

Back to comp.lang.c | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

Re: lvalue types Tim Rentsch <txr@alumni.caltech.edu> - 2018-03-19 09:54 -0700
  Re: lvalue types Keith Thompson <kst-u@mib.org> - 2018-03-19 11:52 -0700
    Re: lvalue types Tim Rentsch <txr@alumni.caltech.edu> - 2018-03-26 23:44 -0700
      Re: lvalue types Keith Thompson <kst-u@mib.org> - 2018-03-27 09:14 -0700
        Re: lvalue types supercat@casperkitty.com - 2018-03-27 12:21 -0700
          Re: lvalue types Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-28 17:01 -0700
          Re: lvalue types Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-29 01:54 -0700
      Re: lvalue types supercat@casperkitty.com - 2018-03-27 12:09 -0700
        Re: lvalue types Steven Petruzzellis <frelwizzen@gmail.com> - 2018-03-28 10:48 -0700
  Re: lvalue types supercat@casperkitty.com - 2018-03-19 12:27 -0700

csiph-web