Casts on lvalues

Discussion in 'C Programming' started by BartC, Dec 2, 2012.

  1. BartC

    BartC Guest

    Suppose I have these types:

    #define byte unsigned char

    typedef struct {
    int a,b,c,d;
    } R; /* assume this is 16 bytes */

    And these variables:

    int n; /* represents a *byte* offset */
    R* p;

    I want to be able to do the following:
    p += n;

    but it doesn't work because n is a byte offset; it's not in terms of R
    objects. But the obvious cast:

    (byte*)p+=n;

    doesn't appear to compile. The workarounds seem to be:

    p += n/sizeof(R);

    which I don't like. Even though p is always aligned (and n is known to be a
    multiple of 16), and I know the divide will cancel out, it seems funny
    having to introduce a divide op in the first place. And:

    p = (R*)((byte*)p+n);

    which is what I'm using but looks very untidy in real code.

    In any case, the question remains, *is* there a way to cast an lvalue as
    I've shown above?

    --
    Bartc
    BartC, Dec 2, 2012
    #1
    1. Advertising

  2. BartC

    SG Guest

    Am 02.12.2012 14:23, schrieb BartC:
    > Suppose I have these types:
    >
    > #define byte unsigned char
    >
    > typedef struct {
    > int a,b,c,d;
    > } R; /* assume this is 16 bytes */
    >
    > And these variables:
    >
    > int n; /* represents a *byte* offset */
    > R* p;
    >
    > I want to be able to do the following:
    > p += n;
    >
    > but it doesn't work because n is a byte offset; it's not in terms of R
    > objects. But the obvious cast:
    >
    > (byte*)p+=n;
    >
    > doesn't appear to compile. The workarounds seem to be:
    >
    > p += n/sizeof(R);
    >
    > which I don't like. Even though p is always aligned (and n is known to be a
    > multiple of 16), and I know the divide will cancel out, it seems funny
    > having to introduce a divide op in the first place. And:
    >
    > p = (R*)((byte*)p+n);
    >
    > which is what I'm using but looks very untidy in real code.
    >
    > In any case, the question remains, *is* there a way to cast an lvalue as
    > I've shown above?


    In C++ there is. But you would invoke undefined behaviour because doing
    it in this case violates the aliasing rule. I really don't see the
    problem with

    p += n/sizeof(R);

    It looks like exactly the thing you should write. Maybe throw an

    assert(n % sizeof(R) == 0);

    in there as well.
    SG, Dec 2, 2012
    #2
    1. Advertising

  3. "BartC" <> writes:

    > Suppose I have these types:
    >
    > #define byte unsigned char
    >
    > typedef struct {
    > int a,b,c,d;
    > } R; /* assume this is 16 bytes */
    >
    > And these variables:
    >
    > int n; /* represents a *byte* offset */
    > R* p;
    >
    > I want to be able to do the following:
    > p += n;
    >
    > but it doesn't work because n is a byte offset; it's not in terms of R
    > objects. But the obvious cast:
    >
    > (byte*)p+=n;
    >
    > doesn't appear to compile. The workarounds seem to be:
    >
    > p += n/sizeof(R);
    >
    > which I don't like. Even though p is always aligned (and n is known to be a
    > multiple of 16), and I know the divide will cancel out, it seems funny
    > having to introduce a divide op in the first place. And:
    >
    > p = (R*)((byte*)p+n);
    >
    > which is what I'm using but looks very untidy in real code.
    >
    > In any case, the question remains, *is* there a way to cast an lvalue as
    > I've shown above?


    No, I don't think so. Certainly not directly -- a cast expression is
    not a lvalue. You can do dangerous thing like:

    *(byte **)&p += n; /* don't do this!! */

    or use a union with an R * and a char * pointer in it, but both
    techniques rely on the representation of char and struct pointers being
    the same -- they re-interpret the pointer rather than converting it.

    I think your best bet is to tidy up what you currently use

    static inline void *addr_inc(void *p, int n) { return (char *)p + n; }

    will let you write p = addr_inc(p, n); which is much less messy and not
    hard to follow.

    --
    Ben.
    Ben Bacarisse, Dec 2, 2012
    #3
  4. "BartC" <> writes:
    > Suppose I have these types:
    >
    > #define byte unsigned char


    Why are you using a macro rather than a typedef?

    > typedef struct {
    > int a,b,c,d;
    > } R; /* assume this is 16 bytes */


    Or you could assume that it's `sizeof R` bytes.

    > And these variables:
    >
    > int n; /* represents a *byte* offset */
    > R* p;
    >
    > I want to be able to do the following:
    > p += n;
    >
    > but it doesn't work because n is a byte offset; it's not in terms of R
    > objects. But the obvious cast:
    >
    > (byte*)p+=n;
    >
    > doesn't appear to compile.


    Right. A cast operator doesn't require an lvalue as its operand.
    If the operand happens to be an lvalue, it's not treated as one.
    It undergoes an "lvalue conversion" as described in N1570 6.3.2.1p2.
    The result of a cast is not an lvalue.

    > The workarounds seem to be:
    >
    > p += n/sizeof(R);
    >
    > which I don't like. Even though p is always aligned (and n is known to be a
    > multiple of 16), and I know the divide will cancel out, it seems funny
    > having to introduce a divide op in the first place. And:
    >
    > p = (R*)((byte*)p+n);
    >
    > which is what I'm using but looks very untidy in real code.
    >
    > In any case, the question remains, *is* there a way to cast an lvalue as
    > I've shown above?


    No.

    Why is n a byte offset in the first place? You're dealing with
    objects of your anonymous struct type; can't you just give your
    struct a name and make p a pointer to it? If you need a byte
    pointer, you can convert a struct pointer to byte*.

    Incidentally, I'd probably use unsigned char directly; it's clear enough
    and doesn't make the reader wonder how "byte" has been defined.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 2, 2012
    #4
  5. BartC

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> writes:


    >> int n; /* represents a *byte* offset */
    >> R* p;
    >>
    >> I want to be able to do the following:
    >> p += n;
    >>
    >> but it doesn't work because n is a byte offset; it's not in terms of R
    >> objects. But the obvious cast:


    > Why is n a byte offset in the first place?


    The offsets come from externally generated data, and initially were simple
    counts: +2, -1 etc. The code looked like this:

    R *p,*q;

    p=q+n;

    Very nice. Then I noticed this addition involved internally multiplying n by
    16 (or a shift as it was), which wasn't so nice! It was just as easy to
    generate these numbers as multiples of 16 anyway (+32, -16 etc) so I did
    that. But then the code wasn't so pretty.

    --
    Bartc
    BartC, Dec 2, 2012
    #5
  6. BartC

    Eric Sosman Guest

    On 12/2/2012 4:21 PM, pete wrote:
    > Keith Thompson wrote:
    >
    >> The result of a cast is not an lvalue.

    >
    > I don't think that the standard explicitly states this;


    It's in a footnote to 6.5.4p5. Footnotes are non-normative,
    but then there's the definition of lvalue in 6.3.2.1p1:

    "An lvalue is an expression [...] that potentially
    designates an object [...]"

    There is no cast that produces an object designator,[*] hence
    there is no cast that produces an lvalue.

    [*] You can (sometimes) derive an lvalue from the result
    of a cast by applying an operator to it, as in

    * (unsigned char*)&foo = 42;

    or
    ((struct baz*)&foo) -> mumble = 17;

    > but as far as I can tell,
    > the result of any conversion of the type of any expression,
    > is not an lvalue.


    Even a non-conversion is not an lvalue:

    double trouble;
    (double)trouble = 3.14; // BZZZT!

    --
    Eric Sosman
    d
    Eric Sosman, Dec 2, 2012
    #6
  7. BartC

    James Kuyper Guest

    On 12/02/2012 04:21 PM, pete wrote:
    > Keith Thompson wrote:
    >
    >> The result of a cast is not an lvalue.

    >
    > I don't think that the standard explicitly states this;
    > but as far as I can tell,
    > the result of any conversion of the type of any expression,
    > is not an lvalue.


    The standard says that something is not an lvalue in only a few places:
    6.3.2.1p3 when an lvalue of array type is converted to a pointer to its
    first element.
    6.5.2.3p3 function_returning_struct_type().member
    6.5.16p3 assignment expression

    Most of the time, it only says when something IS an lvalue:
    6.5.1p2 object_identifier
    6.5.1p4 "string literal"
    6.5.1p5 (lvalue)
    6.5.1.1p4 _Generic(x, int:lvalue1, default:lvalue2)
    6.5.2.3p3 lvalue.member
    6.5.2.3p4 expression->member
    6.5.2.5p4 compound literal
    6.5.3.4p4 *pointer_to_object
    6.9.1p9 function parameter identifier
    --
    James Kuyper
    James Kuyper, Dec 3, 2012
    #7
  8. In article <xDIus.482873$4>, BartC <> wrote:
    >
    >I want to be able to do the following:
    > p += n;
    >
    >but it doesn't work because n is a byte offset; it's not in terms of R
    >objects. But the obvious cast:
    >
    > (byte*)p+=n;
    >
    >doesn't appear to compile. The workarounds seem to be:
    >
    > p += n/sizeof(R);


    Other options:

    p += n/sizeof(*p);

    p = (R *)((byte *)p +n)

    But frankly, none of these is a very good choice. If I were
    code-reviewing something like this, I'd ask the programmer what it is
    that they're *really* trying to do. Constructs like this are
    a likely sign of broken logic and broken code.

    Note also that the n/sizeof(...) variant fails horribly if the
    byte offset isn't a multiple of the structure size.

    Not to say that something like this should *never* be written --
    I can think of a number of cases where multiple data structures
    might be packed into a buffer, in which case this is exactly the
    sort of thing you might be doing. But in cases like this, you're
    best off keeping p as a byte pointer and just casting it to a
    pointer to R when you need to dereference it.

    I'm assuming you're taking the proper precautions w.r.t. alignment
    issues. That's a whole 'nother discussion.

    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
    Edward A. Falk, Dec 4, 2012
    #8
  9. BartC

    BartC Guest

    "Edward A. Falk" <> wrote in message
    news:k9m2m6$vfu$...
    > In article <xDIus.482873$4>, BartC <> wrote:
    >>
    >>I want to be able to do the following:
    >> p += n;
    >>
    >>but it doesn't work because n is a byte offset; it's not in terms of R


    > Other options:
    >
    > p += n/sizeof(*p);
    >
    > p = (R *)((byte *)p +n)
    >
    > But frankly, none of these is a very good choice. If I were
    > code-reviewing something like this, I'd ask the programmer what it is
    > that they're *really* trying to do. Constructs like this are
    > a likely sign of broken logic and broken code.


    I've already said elsewhere that using an object rather than a byte offset
    involved an unnecessary multiplication or shift.

    I noticed it when I wanted shadow some functions with assembly code.

    --
    Bartc
    BartC, Dec 5, 2012
    #9
  10. "BartC" <> writes:

    > "Edward A. Falk" <> wrote in message
    > news:k9m2m6$vfu$...
    > I've already said elsewhere that using an object rather than a byte
    > offset involved an unnecessary multiplication or shift.


    It was not unnecessary. It's called pointer arithmetic and allowed you
    to use more elegant code at slightly higher level of abstraction that
    is supposed to more closely represent your intentions.

    You have decided this abstraction is unnecessary, because you feel you
    need to optimise this shift/multiplication away (and maybe you do, I
    couldn't possibly know that). More specifically, you have implicitly
    decided this optimisation is worth the trade off in form of increased
    complexity of the code (decreased readability or whatever it is that
    bugged you enough to actually ask about it, seeking a different way to
    express what you are doing).

    There's no free lunch. Now deal with the consequences, or revert your
    decision, as others already presented answer to your original question.

    Regards,
    Piotr Kalinowski
    Piotr Kalinowski, Dec 5, 2012
    #10
  11. BartC

    BartC Guest

    "Piotr Kalinowski" <> wrote in message
    news:...
    > "BartC" <> writes:
    >
    >> I've already said elsewhere that using an object rather than a byte
    >> offset involved an unnecessary multiplication or shift.

    >
    > It was not unnecessary. It's called pointer arithmetic and allowed you
    > to use more elegant code at slightly higher level of abstraction that
    > is supposed to more closely represent your intentions.


    Yet, C allows to you to do this - cast the target of a pointer - in an
    rvalue expression.

    > You have decided this abstraction is unnecessary, because you feel you
    > need to optimise this shift/multiplication away (and maybe you do, I
    > couldn't possibly know that). More specifically, you have implicitly
    > decided this optimisation is worth the trade off in form of increased
    > complexity of the code (decreased readability or whatever it is that
    > bugged you enough to actually ask about it, seeking a different way to
    > express what you are doing).


    I asked about doing the same on the left side of an assignment.

    It's this asymmetry that is the issue.

    --
    Bartc
    BartC, Dec 5, 2012
    #11
  12. BartC

    Eric Sosman Guest

    On 12/5/2012 11:47 AM, BartC wrote:
    >
    > Yet, C allows to you to do this - cast the target of a pointer - in an
    > rvalue expression.


    No: C allows you to apply a cast operator to a *value* (which
    may have been extracted from a pointer's target), not to the target
    itself.

    >[...]
    > I asked about doing the same on the left side of an assignment.
    >
    > It's this asymmetry that is the issue.


    Um, er, assignment itself is asymmetric ...

    --
    Eric Sosman
    d
    Eric Sosman, Dec 5, 2012
    #12
  13. BartC

    BartC Guest

    "Eric Sosman" <> wrote in message
    news:k9o2b3$bcb$...
    > On 12/5/2012 11:47 AM, BartC wrote:
    >>
    >> Yet, C allows to you to do this - cast the target of a pointer - in an
    >> rvalue expression.

    >
    > No: C allows you to apply a cast operator to a *value* (which
    > may have been extracted from a pointer's target), not to the target
    > itself.


    Take this example:

    typedef unsigned char byte;

    int a = 0x12345678;
    int* p = &a;

    printf( "*p = %X\n", *p);
    printf( "*p = %X\n", *(byte*)p);

    In the last line, p is made to behave as though it was a byte pointer,
    rather than an int pointer. And quite likely, a byte value is requested from
    memory rather than an int one. Also, in most cases, the value of the pointer
    need not be changed.

    The effect is to change the target of the pointer *type*, rather than any
    actual value.

    >>[...]
    >> I asked about doing the same on the left side of an assignment.
    >>
    >> It's this asymmetry that is the issue.

    >
    > Um, er, assignment itself is asymmetric ...


    Plenty of terms can appear interchangeably on both left and right sides.

    But while A can appear on either side, (T)A can't. And there doesn't appear
    to be a convincing reason why not.

    --
    Bartc
    BartC, Dec 5, 2012
    #13
  14. BartC

    James Kuyper Guest

    On 12/05/2012 01:39 PM, BartC wrote:
    ....
    >> On 12/5/2012 11:47 AM, BartC wrote:

    ....
    >>> I asked about doing the same on the left side of an assignment.

    ....
    > But while A can appear on either side, (T)A can't. And there doesn't appear
    > to be a convincing reason why not.


    The reason is the same as the one that Keith gave to the similar
    question you asked at the start of this thread about compound assignment
    expressions: "The result of a cast is not an lvalue." Since it's not an
    lvalue, no memory is set aside to store anything in it. It appears that
    you want

    (T)A op= B

    to have the meaning that can currently be expressed in standard C as

    A = (T)A op B.

    but it's not clear to me what you want

    (T)A = B

    to mean. Can you express it in terms of standard C, the way that I did
    above for op=? Consider:

    int a=3;
    (double)a = 3.14;

    Currently, this is equivalent to

    3.0 = 3.14;

    and therefore disallowed for the same reason that 3.0 = 3.14 is. What
    would you like it to do in a revised version of C?
    James Kuyper, Dec 5, 2012
    #14
  15. BartC

    Eric Sosman Guest

    On 12/5/2012 1:39 PM, BartC wrote:
    >
    >
    > "Eric Sosman" <> wrote in message
    > news:k9o2b3$bcb$...
    >> On 12/5/2012 11:47 AM, BartC wrote:
    >>>
    >>> Yet, C allows to you to do this - cast the target of a pointer - in an
    >>> rvalue expression.

    >>
    >> No: C allows you to apply a cast operator to a *value* (which
    >> may have been extracted from a pointer's target), not to the target
    >> itself.

    >
    > Take this example:
    >
    > typedef unsigned char byte;
    >
    > int a = 0x12345678;
    > int* p = &a;
    >
    > printf( "*p = %X\n", *p);
    > printf( "*p = %X\n", *(byte*)p);
    >
    > In the last line, p is made to behave as though it was a byte pointer,
    > rather than an int pointer. And quite likely, a byte value is requested
    > from memory rather than an int one. Also, in most cases, the value of
    > the pointer need not be changed.


    No: `p' is not "made to behave" like anything other than
    what it is. `p' is an identifier, which (in this context) is
    seen first as a primary expression (6.5.1p2), and then as an
    lvalue (6.3.2.1p1). The object designated by this lvalue is
    consulted to obtain a value (6.3.2.1p2); this value points at
    the object designated by `a' and has the type `int*'.

    The `(byte*)' operator converts the extracted value to the
    `(unsigned char*)' type (6.5.4), and this converted value points
    at the lowest-addressed constituent byte of the object designated
    by `a' (6.3.2.3p7).

    The `*' operator uses the `(unsigned char*)' value produced
    by the cast to designate the pointed-to byte (6.5.3.2p4), and
    this designation is an lvalue (6.3.2.1p1 again), from which is
    extracted the value stored in the designated byte (6.3.2.1p2
    again), which is a value of type `unsigned char'. The default
    argument promotions convert this value to `int' or `unsigned int',
    and lo! we've computed an argument for printf().

    `p' is unchanged throughout all of this. Its value has not
    changed, its behavior has not changed, its nature has not changed.
    It has not put on makeup, adopted a foreign accent, or affected a
    silly walk. It is still an `int*' aimed at the object designated
    by `a'.

    > The effect is to change the target of the pointer *type*, rather than
    > any actual value.


    No. See above -- or ask "Has the type of `p's target changed?"
    Since `p's target is exactly what it was to begin with, and has made
    no sorties into strange territory and back again, the answer is "No."
    There has been no change, hence "the effect is to change" is wrong.

    >>> [...]
    >>> I asked about doing the same on the left side of an assignment.
    >>>
    >>> It's this asymmetry that is the issue.

    >>
    >> Um, er, assignment itself is asymmetric ...

    >
    > Plenty of terms can appear interchangeably on both left and right sides.
    >
    > But while A can appear on either side, (T)A can't. And there doesn't
    > appear to be a convincing reason why not.


    If you're not convinced that an lvalue is different from other
    kinds of expressions, you're beyond my power to educate -- but that's
    nothing new.

    --
    Eric Sosman
    d
    Eric Sosman, Dec 5, 2012
    #15
  16. BartC

    Greg Martin Guest

    On 12-12-05 10:39 AM, BartC wrote:
    >
    >
    > "Eric Sosman" <> wrote in message
    > news:k9o2b3$bcb$...
    >> On 12/5/2012 11:47 AM, BartC wrote:
    >>>
    >>> Yet, C allows to you to do this - cast the target of a pointer - in an
    >>> rvalue expression.

    >>
    >> No: C allows you to apply a cast operator to a *value* (which
    >> may have been extracted from a pointer's target), not to the target
    >> itself.

    >
    > Take this example:
    >
    > typedef unsigned char byte;
    >
    > int a = 0x12345678;
    > int* p = &a;
    >
    > printf( "*p = %X\n", *p);
    > printf( "*p = %X\n", *(byte*)p);
    >
    > In the last line, p is made to behave as though it was a byte pointer,
    > rather than an int pointer. And quite likely, a byte value is requested
    > from memory rather than an int one. Also, in most cases, the value of
    > the pointer need not be changed.
    >
    > The effect is to change the target of the pointer *type*, rather than
    > any actual value.
    >
    >>> [...]
    >>> I asked about doing the same on the left side of an assignment.
    >>>
    >>> It's this asymmetry that is the issue.

    >>
    >> Um, er, assignment itself is asymmetric ...

    >
    > Plenty of terms can appear interchangeably on both left and right sides.
    >
    > But while A can appear on either side, (T)A can't. And there doesn't
    > appear to be a convincing reason why not.
    >


    Since you aren't actually changing A by (T)A but rather saying treat
    it's value like it's a T rather then A's declared type, it doesn't
    really make sense. I can't see the value of momentarily treating A like
    it's a T just to fool the compiler. Presuming T is larger then A are you
    asking the compiler to overwrite the memory adjacent to A? Probably not.
    Your probably asking it to cast the value to A's type which is more
    logically written A = (A_Type) some_T; // IMO.

    Excuse me if I've missed your meaning but I think if you think about
    what a cast is you'll see it doesn't apply to lvalues.
    Greg Martin, Dec 5, 2012
    #16
  17. BartC

    BartC Guest

    "Greg Martin" <> wrote in message
    news:U4Ovs.586$...
    > On 12-12-05 10:39 AM, BartC wrote:


    >> Plenty of terms can appear interchangeably on both left and right sides.
    >>
    >> But while A can appear on either side, (T)A can't. And there doesn't
    >> appear to be a convincing reason why not.
    >>

    >
    > Since you aren't actually changing A by (T)A but rather saying treat it's
    > value like it's a T rather then A's declared type, it doesn't really make
    > sense.


    Isn't that the point of having casts?

    > I can't see the value of momentarily treating A like it's a T just to fool
    > the compiler.


    On a platform that you know inside-out, and where the alternative is to do
    exactly the same but using assembly code with all of it's disadvantages,
    there there is plenty of value in doing it.

    When you have a datablock of mixed-type data, and traversing it via a
    pointer, then you might expect to switch pointer types all the time, rather
    than messing with unions and memcpys.

    > Presuming T is larger then A are you asking the compiler to overwrite the
    > memory adjacent to A? Probably not.


    Yes. But you'd be sensible enough not to do that.

    > Your probably asking it to cast the value to A's type which is more
    > logically written A = (A_Type) some_T; // IMO.


    That's not quite the same. See the example I gave in my reply to James.

    --
    Bartc
    BartC, Dec 5, 2012
    #17
  18. "BartC" <> writes:

    > "Eric Sosman" <> wrote in message
    > news:k9o2b3$bcb$...

    <snip>
    >> Um, er, assignment itself is asymmetric ...

    >
    > Plenty of terms can appear interchangeably on both left and right sides.
    >
    > But while A can appear on either side, (T)A can't. And there doesn't
    > appear to be a convincing reason why not.


    B = (T)A; // OK
    (T)A = B; // not OK
    B = +A; // OK
    +A = B; // not OK
    B = !A; // OK
    !A = B; // not OK
    B = A + C; // OK
    A + C = B; // not OK

    .... and so on. There's a pattern.

    --
    Ben.
    Ben Bacarisse, Dec 5, 2012
    #18
  19. BartC

    BartC Guest

    "James Kuyper" <> wrote in message
    news:...
    > On 12/05/2012 01:39 PM, BartC wrote:


    >> But while A can appear on either side, (T)A can't. And there doesn't
    >> appear
    >> to be a convincing reason why not.

    >
    > The reason is the same as the one that Keith gave to the similar
    > question you asked at the start of this thread about compound assignment
    > expressions: "The result of a cast is not an lvalue."


    OK, I get that now. But that's only because the Book says so.

    >It appears that you want
    >
    > (T)A op= B
    >
    > to have the meaning that can currently be expressed in standard C as
    >
    > A = (T)A op B.


    It's not quite that either, because this might involve unwanted int/float
    conversions.

    > but it's not clear to me what you want
    >
    > (T)A = B
    >
    > to mean. Can you express it in terms of standard C, the way that I did
    > above for op=?


    It means: "pretend that A is a variable of type T for this assignment".

    > Consider:
    >
    > int a=3;
    > (double)a = 3.14;
    >
    > Currently, this is equivalent to
    >
    > 3.0 = 3.14;
    >
    > and therefore disallowed for the same reason that 3.0 = 3.14 is. What
    > would you like it to do in a revised version of C?


    Well in this case it wouldn't do anything too useful! But turning it around
    a little:

    double a;

    (int)a = 3142;

    This just writes the bit-pattern for integer 3142 in (on my machine) the
    bottom half of a. But that, I can currently do in C using instead:

    *(int*)&a = 3142;

    (even though people don't seem to like this either). My original example was
    more like this:

    int* P;

    ++(char*)P;

    ie. treat P as as a char* pointer (so that on my machine, the value in P
    increments by 1 instead of 4).

    I used to do this stuff in another language something like this:

    double a;
    int n;
    equivalence(a,n) /* a and n share the same memory location */

    n=3142; /* does what I tried to do above */

    OK, I understand in C, you have to use unions and memcpys and things. But
    that's not always straightforward (for example, 'a' might be an extern
    variable, or part of an array).


    --
    Bartc
    BartC, Dec 5, 2012
    #19
  20. BartC

    BartC Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > "BartC" <> writes:
    >
    >> "Eric Sosman" <> wrote in message
    >> news:k9o2b3$bcb$...

    > <snip>
    >>> Um, er, assignment itself is asymmetric ...

    >>
    >> Plenty of terms can appear interchangeably on both left and right sides.
    >>
    >> But while A can appear on either side, (T)A can't. And there doesn't
    >> appear to be a convincing reason why not.

    >
    > B = (T)A; // OK
    > (T)A = B; // not OK
    > B = +A; // OK
    > +A = B; // not OK
    > B = !A; // OK
    > !A = B; // not OK
    > B = A + C; // OK
    > A + C = B; // not OK
    >
    > ... and so on. There's a pattern.


    OK, I see it. But: the (T)A=B example might be done instead as:

    memcpy(&A, &B, sizeof(T));

    So it expresses something that could conceivably make sense. Unlike the
    other examples that don't!

    --
    Bartc
    BartC, Dec 5, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mantorok Redgormor

    lvalues -> incomplete types

    Mantorok Redgormor, Feb 6, 2004, in forum: C Programming
    Replies:
    7
    Views:
    421
  2. Replies:
    23
    Views:
    1,425
    Skarmander
    Sep 21, 2006
  3. Lvalues and Rvalues

    , Oct 14, 2006, in forum: C Programming
    Replies:
    3
    Views:
    348
    SM Ryan
    Oct 14, 2006
  4. jacob navia

    casts and lvalues

    jacob navia, Jun 24, 2007, in forum: C Programming
    Replies:
    68
    Views:
    1,411
    Keith Thompson
    Jun 27, 2007
  5. Replies:
    18
    Views:
    554
    Keith Thompson
    Aug 6, 2008
Loading...

Share This Page