— conversion of array to pointer not limited to lvalues

Discussion in 'C Programming' started by nicolas.sitbon@gmail.com, Aug 4, 2008.

  1. Guest

    hi everybody, In the new feature of C99, i find "— conversion of array
    to pointer not limited to lvalues" : what does it mean? I don't find
    any difference between C90 and C99 about conversion of array to
    pointer.
    Thanks.
    , Aug 4, 2008
    #1
    1. Advertising

  2. Chris Torek Guest

    Re: conversion of array to pointer not limited to lvalues

    In article <>
    <> wrote:
    >hi everybody, In the new feature of C99, i find "conversion of array
    >to pointer not limited to lvalues" : what does it mean?


    It means:

    #define N 100 /* or some other constant */

    struct A {
    char arr[N];
    };

    struct A f(void);

    void example(void) {
    char c;

    c = f().arr[10];
    }

    is now valid (it was not valid in C89). The function f() returns
    an "rvalue" (or more simply, a "value"), not an "lvalue" (something
    that designates, or at least potentially designates, an object).

    In most C code, the only time you encounter an array, it is an
    array object -- an lvalue -- as in:

    char buf[30];
    ...
    buf[10] = 'x';

    Here "buf" names the entire array, but the array is an object --
    a region of data storage; in this case it is the array named "buf"
    -- and the <object, array N of T, buf> triple is converted to a
    <value, pointer to T, &buf[0]> triple. That is, the "lvalue" that
    names the entire array is converted to an "rvalue" (i.e., an ordinary
    value) that points to the first element of the array.

    In C89, only lvalue-arrays were converted to rvalue-pointers.
    Since rvalue-arrays are relatively rare -- they arise only from
    function calls like the one above, and some other rarely-encountered
    expressions -- one tends not to see this in real C code.

    (The other reason one tends not to find this in "real" or "working"
    C code is that compilers given source code like this will, at least
    relatively often, produce object code that does not work correctly.
    Even in C99, it is somewhat hard to use this conversion safely.
    Consider, for instance:

    void bad_example(void) {
    char *p;

    p = f().arr;
    printf("[0] = %c\n", p[0]);
    printf("[4] = %c\n", p[4]);
    }

    Depending on how the call is implemented, p[0] and p[4] may well
    no longer exist by the time the printf() calls are made. The first
    printf() may print the desired value, but the call to printf() may
    change the byte accessed by the second call, so that the second
    printf() prints something other than what the programmer expected.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: gmail (figure it out) http://web.torek.net/torek/index.html
    Chris Torek, Aug 4, 2008
    #2
    1. Advertising

  3. Guest

    Re: conversion of array to pointer not limited to lvalues

    I'm sory but I don't understand the difference between a lvalue-arrays
    and a rvalue-arrays?
    Are you saying that
    struct A
    {
    char arr[N];
    };

    and
    char arr2[N];
    are conceptually different?
    , Aug 4, 2008
    #3
  4. On Mon, 4 Aug 2008 10:44:05 -0700 (PDT),
    wrote:

    >hi everybody, In the new feature of C99, i find "— conversion of array
    >to pointer not limited to lvalues" : what does it mean? I don't find
    >any difference between C90 and C99 about conversion of array to
    >pointer.


    You didn't look carefully enough, though I don't know what the real
    impact of the wording change is.

    In C89, para 3.2.2.1 says "Except when ..., an lvalue that has
    type ``array of type '' is converted ..."

    In C99, para 6.3.2.1-3 say "Except when ..., an expression that has
    type ‘‘array of type’’ is converted ..."

    In the new wording, the expression need not be an lvalue. Maybe
    someone who worked on the standard can explain how this affects the
    average programmer or if it is something only a compiler writer would
    care about.

    --
    Remove del for email
    Barry Schwarz, Aug 4, 2008
    #4
  5. Re: conversion of array to pointer not limited to lvalues

    On Mon, 04 Aug 2008 12:39:45 -0700, nicolas.sitbon wrote:
    > I'm sory but I don't understand the difference between a lvalue-arrays
    > and a rvalue-arrays?
    > Are you saying that
    > struct A
    > {
    > char arr[N];
    > };
    >
    > and
    > char arr2[N];
    > are conceptually different?


    Not directly, as far as the array is concerned. However, the former is an
    allowable function return type, while the latter is not.
    Harald van Dijk, Aug 4, 2008
    #5
  6. santosh Guest

    Re: conversion of array to pointer not limited to lvalues

    wrote:

    > I'm sory but I don't understand the difference between a lvalue-arrays
    > and a rvalue-arrays?
    > Are you saying that
    > struct A
    > {
    > char arr[N];
    > };
    >
    > and
    > char arr2[N];
    > are conceptually different?


    Aren't they? They are different types. The first one is type struct A
    and the second one is type char [N].

    But the point is wrapping an array within a structure allows one to
    return an array from functions, which cannot return plain arrays.
    However the manner in which it is accessed is different from how you
    would normally access an array, and this has been standardised by C99.
    Since functions return values, you must store the entire structure (or
    at least it's array member) in another object or you will lose it.

    Please see Chris Torek's post. You can't get a better explanation than
    that.
    santosh, Aug 4, 2008
    #6
  7. Guest

    Re: conversion of array to pointer not limited to lvalues

    On 4 août, 21:56, Harald van Dijk <> wrote:
    > On Mon, 04 Aug 2008 12:39:45 -0700, nicolas.sitbon wrote:
    > > I'm sory but I don't understand the difference between a lvalue-arrays
    > > and a rvalue-arrays?
    > > Are you saying that
    > > struct A
    > > {
    > >    char arr[N];
    > > };

    >
    > > and
    > > char arr2[N];
    > > are conceptually different?

    >
    > Not directly, as far as the array is concerned. However, the former is an
    > allowable function return type, while the latter is not.


    the structure is returned, not the table directly.
    , Aug 4, 2008
    #7
  8. santosh Guest

    Re: conversion of array to pointer not limited to lvalues

    wrote:

    > On 4 août, 21:56, Harald van D?k <> wrote:
    >> On Mon, 04 Aug 2008 12:39:45 -0700, nicolas.sitbon wrote:
    >> > I'm sory but I don't understand the difference between a
    >> > lvalue-arrays and a rvalue-arrays?
    >> > Are you saying that
    >> > struct A
    >> > {
    >> > char arr[N];
    >> > };

    >>
    >> > and
    >> > char arr2[N];
    >> > are conceptually different?

    >>
    >> Not directly, as far as the array is concerned. However, the former
    >> is an allowable function return type, while the latter is not.

    >
    > the structure is returned, not the table directly.


    A value of type struct A is returned which contains an array member of
    type char [n]. You can do this too:

    struct A ret = foo(); /* returns a struct A value */
    printf("%c\n", ret.arr[0]);

    instead of

    printf("%c\n", foo().arr[0]);
    santosh, Aug 4, 2008
    #8
  9. Guest

    Re: conversion of array to pointer not limited to lvalues

    On 4 août, 22:06, santosh <> wrote:
    > wrote:
    > > On 4 août, 21:56, Harald van D?k <> wrote:
    > >> On Mon, 04 Aug 2008 12:39:45 -0700, nicolas.sitbon wrote:
    > >> > I'm sory but I don't understand the difference between a
    > >> > lvalue-arrays and a rvalue-arrays?
    > >> > Are you saying that
    > >> > struct A
    > >> > {
    > >> > char arr[N];
    > >> > };

    >
    > >> > and
    > >> > char arr2[N];
    > >> > are conceptually different?

    >
    > >> Not directly, as far as the array is concerned. However, the former
    > >> is an allowable function return type, while the latter is not.

    >
    > > the structure is returned, not the table directly.

    >
    > A value of type struct A is returned which contains an array member of
    > type char [n]. You can do this too:
    >
    >  struct A ret = foo(); /* returns a struct A value */
    >  printf("%c\n", ret.arr[0]);
    >
    > instead of
    >
    >  printf("%c\n", foo().arr[0]);


    OK, I know that, but except the fact that we can return the table
    (which is in a structure), what's the difference between the two table?
    , Aug 4, 2008
    #9
  10. Re: conversion of array to pointer not limited to lvalues

    On Mon, 4 Aug 2008 12:39:45 -0700 (PDT),
    wrote:

    >I'm sory but I don't understand the difference between a lvalue-arrays
    >and a rvalue-arrays?
    >Are you saying that
    >struct A
    >{
    > char arr[N];
    >};
    >
    >and
    >char arr2[N];
    >are conceptually different?


    I don't understand many facets of lvalue and rvalue either but one
    obvious difference is that your struct is only a declaration of a type
    while your arr2 is the definition of an object. If you define a
    struct A named x, there is still one obvious difference. Passing x to
    a function will result in a complete copy of the array arr being
    passed to the function. Passing arr2 to a similar function will
    result in the address of the array being passed. In the first case,
    updates to array elements are local to the called function. In the
    second, updates are made directly to the array in the calling
    function.

    --
    Remove del for email
    Barry Schwarz, Aug 4, 2008
    #10
  11. Guest

    Re: conversion of array to pointer not limited to lvalues

    On 4 août, 23:01, Barry Schwarz <> wrote:
    > On Mon, 4 Aug 2008 12:39:45 -0700 (PDT),
    > wrote:
    >
    > >I'm sory but I don't understand the difference between a lvalue-arrays
    > >and a rvalue-arrays?
    > >Are you saying that
    > >struct A
    > >{
    > >   char arr[N];
    > >};

    >
    > >and
    > >char arr2[N];
    > >are conceptually different?

    >
    > I don't understand many facets of  lvalue and rvalue either but one
    > obvious difference is that your struct is only a declaration of a type
    > while your arr2 is the definition of an object.  If you define a
    > struct A named x, there is still one obvious difference.  Passing x to
    > a function will result in a complete copy of the array arr being
    > passed to the function.  Passing arr2 to a similar function will
    > result in the address of the array being passed.  In the first case,
    > updates to array elements are local to the called function.  In the
    > second, updates are made directly to the array in the calling
    > function.
    >
    > --
    > Remove del for email


    I know all of this details but I have some difficulties with this
    notion of lvalues/rvalues. In all case a table is nothing more than a
    data storage so what's the difference that affects the "l/r
    valuability" (oh my god, my poor English)?.
    , Aug 4, 2008
    #11
  12. Guest

    Re: conversion of array to pointer not limited to lvalues

    wrote:
    > On 4 ao�t, 22:06, santosh <> wrote:
    > > wrote:
    > > > On 4 ao�t, 21:56, Harald van D?k <> wrote:
    > > >> On Mon, 04 Aug 2008 12:39:45 -0700, nicolas.sitbon wrote:
    > > >> > I'm sory but I don't understand the difference between a
    > > >> > lvalue-arrays and a rvalue-arrays?
    > > >> > Are you saying that
    > > >> > struct A
    > > >> > {
    > > >> > char arr[N];
    > > >> > };

    > >
    > > >> > and
    > > >> > char arr2[N];
    > > >> > are conceptually different?

    > >
    > > >> Not directly, as far as the array is concerned. However, the former
    > > >> is an allowable function return type, while the latter is not.

    > >
    > > > the structure is returned, not the table directly.

    > >
    > > A value of type struct A is returned which contains an array member of
    > > type char [n]. You can do this too:
    > >
    > > �struct A ret = foo(); /* returns a struct A value */
    > > �printf("%c\n", ret.arr[0]);
    > >
    > > instead of
    > >
    > > �printf("%c\n", foo().arr[0]);

    >
    > OK, I know that, but except the fact that we can return the table
    > (which is in a structure), what's the difference between the two table?


    None. Everything relevant to your question depends only upon that one
    difference. As a result of that difference, any situation in which C
    requires an lvalue is a situation that an array member of a struct
    value returned by a function call doesn't satisfy. The implications of
    this include the fact that you can't increment/decrement it with ++ or
    --, and you can't assign a value to it. Such an array needn't reside
    in addressable memory, because you can't take the address of that
    array - it might sit in one or more registers. Since the subscript
    operator is normally defined in terms of address arithmetic, you need
    a special case like this to allow the elements of such an array to be
    accessed.
    , Aug 4, 2008
    #12
  13. Re: conversion of array to pointer not limited to lvalues

    writes:
    > On 4 août, 23:01, Barry Schwarz <> wrote:
    >> On Mon, 4 Aug 2008 12:39:45 -0700 (PDT),
    >> wrote:
    >>
    >> >I'm sory but I don't understand the difference between a lvalue-arrays
    >> >and a rvalue-arrays?
    >> >Are you saying that
    >> >struct A
    >> >{
    >> >   char arr[N];
    >> >};

    >>
    >> >and
    >> >char arr2[N];
    >> >are conceptually different?

    >>
    >> I don't understand many facets of  lvalue and rvalue either but one
    >> obvious difference is that your struct is only a declaration of a type
    >> while your arr2 is the definition of an object.  If you define a
    >> struct A named x, there is still one obvious difference.  Passing x to
    >> a function will result in a complete copy of the array arr being
    >> passed to the function.  Passing arr2 to a similar function will
    >> result in the address of the array being passed.  In the first case,
    >> updates to array elements are local to the called function.  In the
    >> second, updates are made directly to the array in the calling
    >> function.

    >
    > I know all of this details but I have some difficulties with this
    > notion of lvalues/rvalues. In all case a table is nothing more than a
    > data storage so what's the difference that affects the "l/r
    > valuability" (oh my god, my poor English)?.


    An lvalue is an expression that designates an object.

    The difference here is that the value returned by a function isn't
    (considered to be) an object, even if it's a structure.

    If a function returns an array -- well, a function *can't* return an
    array, so instead it will typically return a pointer to the first
    element of an array. And that pointer has to point to an object
    that's been created in some other manner (a declared object, a
    malloc()ed object, a string literal, a piece of some larger object,
    etc.).

    If a function returns a structure, it just returns the *value* of that
    structure; conceptually at least, there's no object that holds that
    value and whose address you could take. (In practice, there's likely
    to be a struct object somewhere in memory, created by the code
    generated by the compiler, but that "object" isn't visible as an
    object to C code, so it doesn't count.)

    If the structure contains an array, then you have an array that's not
    an object; the change in C99 allows indexing into that array.

    As far as I know, this case (a function returning a structure that
    contains an array) is the only case where you can have an array
    expression without a corresponding array object.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 5, 2008
    #13
  14. Guest

    Re: conversion of array to pointer not limited to lvalues

    On 5 août, 01:49, Keith Thompson <> wrote:
    > writes:
    > > On 4 août, 23:01, Barry Schwarz <> wrote:
    > >> On Mon, 4 Aug 2008 12:39:45 -0700 (PDT),
    > >> wrote:

    >
    > >> >I'm sory but I don't understand the difference between a lvalue-arrays
    > >> >and a rvalue-arrays?
    > >> >Are you saying that
    > >> >struct A
    > >> >{
    > >> >   char arr[N];
    > >> >};

    >
    > >> >and
    > >> >char arr2[N];
    > >> >are conceptually different?

    >
    > >> I don't understand many facets of  lvalue and rvalue either but one
    > >> obvious difference is that your struct is only a declaration of a type
    > >> while your arr2 is the definition of an object.  If you define a
    > >> struct A named x, there is still one obvious difference.  Passing x to
    > >> a function will result in a complete copy of the array arr being
    > >> passed to the function.  Passing arr2 to a similar function will
    > >> result in the address of the array being passed.  In the first case,
    > >> updates to array elements are local to the called function.  In the
    > >> second, updates are made directly to the array in the calling
    > >> function.

    >
    > > I know all of this details but I have some difficulties with this
    > > notion of lvalues/rvalues. In all case a table is nothing more than a
    > > data storage  so what's the difference that affects the "l/r
    > > valuability" (oh my god, my poor English)?.

    >
    > An lvalue is an expression that designates an object.
    >
    > The difference here is that the value returned by a function isn't
    > (considered to be) an object, even if it's a structure.
    >
    > If a function returns an array -- well, a function *can't* return an
    > array, so instead it will typically return a pointer to the first
    > element of an array.  And that pointer has to point to an object
    > that's been created in some other manner (a declared object, a
    > malloc()ed object, a string literal, a piece of some larger object,
    > etc.).
    >
    > If a function returns a structure, it just returns the *value* of that
    > structure; conceptually at least, there's no object that holds that
    > value and whose address you could take.  (In practice, there's likely
    > to be a struct object somewhere in memory, created by the code
    > generated by the compiler, but that "object" isn't visible as an
    > object to C code, so it doesn't count.)
    >
    > If the structure contains an array, then you have an array that's not
    > an object; the change in C99 allows indexing into that array.
    >
    > As far as I know, this case (a function returning a structure that
    > contains an array) is the only case where you can have an array
    > expression without a corresponding array object.
    >
    > --
    > Keith Thompson (The_Other_Keith)  <http://www.ghoti.net/~kst>
    > Nokia
    > "We must do something.  This is something.  Therefore, we must do this."
    >     -- Antony Jay and Jonathan Lynn, "Yes Minister"


    OK, I understand what you say, sorry and thanks for your explanation.
    it's now clear for me.
    Thanks all.
    , Aug 5, 2008
    #14
  15. Huibert Bol Guest

    Re: conversion of array to pointer not limited to lvalues

    Keith Thompson wrote:

    > As far as I know, this case (a function returning a structure that
    > contains an array) is the only case where you can have an array
    > expression without a corresponding array object.


    A ternairy operator that results in a structure that contains an array
    is a second.

    - Huibert.
    Huibert Bol, Aug 5, 2008
    #15
  16. Re: conversion of array to pointer not limited to lvalues

    Huibert Bol <> writes:
    > Keith Thompson wrote:
    >> As far as I know, this case (a function returning a structure that
    >> contains an array) is the only case where you can have an array
    >> expression without a corresponding array object.

    >
    > A ternairy operator that results in a structure that contains an array
    > is a second.


    Sounds interesting, but I'm not quite seeing it. I'd think that in
    order for the tenary operator to result in such a struct expression,
    its second or third operand would have to be such a struct expression,
    so that's not really a distinct case, any more than a parenthesized
    function call would be.

    I was thinking that a C99 compound literal might be another case, but
    it's not, because it "provides an unnamed object whose value is given
    by the initializer list" (C99 6.5.2.5p4). This is similar to an array
    literal.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 6, 2008
    #16
  17. Re: conversion of array to pointer not limited to lvalues

    On Tue, 05 Aug 2008 18:42:57 -0700, Keith Thompson wrote:
    > Huibert Bol <> writes:
    >> Keith Thompson wrote:
    >>> As far as I know, this case (a function returning a structure that
    >>> contains an array) is the only case where you can have an array
    >>> expression without a corresponding array object.

    >>
    >> A ternairy operator that results in a structure that contains an array
    >> is a second.

    >
    > Sounds interesting, but I'm not quite seeing it. I'd think that in
    > order for the tenary operator to result in such a struct expression, its
    > second or third operand would have to be such a struct expression,


    Right.

    > so
    > that's not really a distinct case, any more than a parenthesized
    > function call would be.


    If a is declared as
    struct A a;
    then
    (rand() ? a : a)
    is not an lvalue, even though a is.

    (a = a)
    is also not an lvalue, and is a third way of getting a non-lvalue
    structure.
    Harald van Dijk, Aug 6, 2008
    #17
  18. Chris Torek Guest

    Re: conversion of array to pointer not limited to lvalues

    >On Tue, 05 Aug 2008 18:42:57 -0700, Keith Thompson wrote:
    >>... I'd think that in order for the tenary operator to result
    >>in such a struct expression, its second or third operand would
    >>have to be such a struct expression,


    (in fact, they must both be struct expressions, with identical
    struct types)

    >> so that's not really a distinct case, any more than a parenthesized
    >> function call would be.


    They convert lvalues to rvalues, though.

    In article <4b568$489948fb$541dfcd3$1.nb.home.nl>
    Harald van Dijk <> wrote:
    >If a is declared as
    > struct A a;
    >then
    > (rand() ? a : a)
    >is not an lvalue, even though a is.
    >
    > (a = a)
    >is also not an lvalue, and is a third way of getting a non-lvalue
    >structure.


    In C++, the rules are different. This is only *almost* irrelevant,
    and this is why: In all of these cases, there is an underlying
    lvalue "out there" (namely, the object named "a" in the above code
    fragmnets), and it would have been possible to define the operators
    so that the result *is* an lvalue. For instance, one could redefine
    the ?: operator such that:

    ((a ? b : c) = d)

    becomes meaningful whenever b and c have identical types, or even
    merely types-that-are-compatible-with-d, with the meaning being
    that of:

    (a ? (b = d) : (c = d))

    and in this case, ?: would not remove "lvalue-ness" from its second
    and third operands. Similarly, assignment could have been defined
    to leave lvalue-ness alone. (They are not, and we have to deal
    with the language as it is, not as it might be, of course. But
    this does relate to C in at least one way: C compiler bugs one
    finds regarding use of func().array_member tend not to affect these
    other forms of expression, or at least not as often, because those
    bugs often arise from compiler-writers making mistakes in tracking
    "lvalue-ness". Such a mistake winds up being "harmless" -- other
    than failure to generate a required diagnostic, anyway -- when
    there is an "underlying lvalue" that the compiler accidentally
    uses. There is one for everything except func().array_member.
    [In the func().array_member case, the "lvalue" the compiler manages
    to come up with is often a stack temporary that is subsequently
    clobbered. The runtime behavior seen when using this can be
    difficult to debug.])
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: gmail (figure it out) http://web.torek.net/torek/index.html
    Chris Torek, Aug 6, 2008
    #18
  19. Re: conversion of array to pointer not limited to lvalues

    Chris Torek <> writes:
    >>On Tue, 05 Aug 2008 18:42:57 -0700, Keith Thompson wrote:
    >>>... I'd think that in order for the tenary operator to result
    >>>in such a struct expression, its second or third operand would
    >>>have to be such a struct expression,

    >
    > (in fact, they must both be struct expressions, with identical
    > struct types)
    >
    >>> so that's not really a distinct case, any more than a parenthesized
    >>> function call would be.

    >
    > They convert lvalues to rvalues, though.


    Yes, thanks, that's the point I was missing. And thanks to Harald
    too.

    [snip]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 6, 2008
    #19
    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:
    424
  2. Replies:
    23
    Views:
    1,429
    Skarmander
    Sep 21, 2006
  3. Lvalues and Rvalues

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

    casts and lvalues

    jacob navia, Jun 24, 2007, in forum: C Programming
    Replies:
    68
    Views:
    1,419
    Keith Thompson
    Jun 27, 2007
  5. Nicklas Karlsson

    lvalues and rvalues

    Nicklas Karlsson, Apr 6, 2010, in forum: C Programming
    Replies:
    127
    Views:
    2,604
    Tim Rentsch
    May 5, 2010
Loading...

Share This Page