pointer to an int array

Discussion in 'C Programming' started by Neo, Jan 3, 2005.

  1. Neo

    Neo Guest

    Hi Folks,


    #include<stdio.h>
    int main()
    {
    int (*p)[10];
    int arr[10];
    int i;

    p = arr; /* <-- compiler warning */
    for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    *((*p) + i) = i;

    printf("%d\n", p[0]);
    }

    return 0;
    }

    In the above program compiler is giving following warning

    $gcc pointer2array.c
    pointer2array.c: In function `main':
    pointer2array.c:8: warning: assignment from incompatible pointer type

    Why the warning?

    O'kay and what is the use of int (*p)[10] type of declaration ?
    Does the compiler perform any check on the array bounds?
    lets say if i declare int arr[12]...
    -Neo
    Neo, Jan 3, 2005
    #1
    1. Advertising

  2. Neo

    Jack Klein Guest

    On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <>
    wrote in comp.lang.c:

    > Hi Folks,
    >
    >
    > #include<stdio.h>
    > int main()
    > {
    > int (*p)[10];
    > int arr[10];
    > int i;
    >
    > p = arr; /* <-- compiler warning */


    The name of an array in an expression, other than when it is the
    operand of the 'sizeof' or '&' operators, is converted to a pointer to
    its first element. So in the statement above, you are assigning the
    address of an int (arr[0]) to a pointer to an array. But arr[0] is an
    int, not an array of ints.

    Replace with:

    p = &arr;

    > for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    > *((*p) + i) = i;
    >
    > printf("%d\n", p[0]);
    > }
    >
    > return 0;
    > }
    >
    > In the above program compiler is giving following warning
    >
    > $gcc pointer2array.c
    > pointer2array.c: In function `main':
    > pointer2array.c:8: warning: assignment from incompatible pointer type
    >
    > Why the warning?
    >
    > O'kay and what is the use of int (*p)[10] type of declaration ?
    > Does the compiler perform any check on the array bounds?
    > lets say if i declare int arr[12]...


    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Jan 3, 2005
    #2
    1. Advertising

  3. Neo

    Neo Guest

    "Jack Klein" <> wrote in message
    news:...
    > On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <>
    > wrote in comp.lang.c:
    >
    >> Hi Folks,
    >>
    >>
    >> #include<stdio.h>
    >> int main()
    >> {
    >> int (*p)[10];
    >> int arr[10];
    >> int i;
    >>
    >> p = arr; /* <-- compiler warning */

    >
    > The name of an array in an expression, other than when it is the
    > operand of the 'sizeof' or '&' operators, is converted to a pointer to
    > its first element. So in the statement above, you are assigning the
    > address of an int (arr[0]) to a pointer to an array. But arr[0] is an
    > int, not an array of ints.
    >
    > Replace with:
    >
    > p = &arr;
    >


    O'kay, dats fine.
    if I change the declaration above as :

    int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with
    unspecified bounds
    int arr[10];
    p = &arr;
    for(i=0; i <= 12; i++){
    *((*p) + i) = i;
    printf("%d\n", p[0]);
    }

    compiler error!
    what's the use of array index in the above declaration?
    as i can go upto 12 or more...

    -Neo



    >> for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    >> *((*p) + i) = i;
    >>
    >> printf("%d\n", p[0]);
    >> }
    >>
    >> return 0;
    >> }
    >>
    >> In the above program compiler is giving following warning
    >>
    >> $gcc pointer2array.c
    >> pointer2array.c: In function `main':
    >> pointer2array.c:8: warning: assignment from incompatible pointer type
    >>
    >> Why the warning?
    >>
    >> O'kay and what is the use of int (*p)[10] type of declaration ?
    >> Does the compiler perform any check on the array bounds?
    >> lets say if i declare int arr[12]...

    >
    > --
    > Jack Klein
    > Home: http://JK-Technology.Com
    > FAQs for
    > comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    > comp.lang.c++ http://www.parashift.com/c -faq-lite/
    > alt.comp.lang.learn.c-c++
    > http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Neo, Jan 3, 2005
    #3
  4. On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
    <> wrote:

    >if I change the declaration above as :
    >
    > int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds
    >
    >compiler error!


    yes, its an error

    >what's the use of array index in the above declaration?


    none - its an illegal construct

    >as i can go upto 12 or more...


    only by invoking undefined behaviour....

    Don't do that.
    --
    Mark McIntyre
    CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

    ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
    Mark McIntyre, Jan 3, 2005
    #4
  5. Neo

    gooch Guest

    You can index up to whatever value you want. p[1000] is fine. The
    result is going to be undefined. In most cases you would get a seg
    fault but that may not be the case. You have to do the bounds checking
    yourself.
    gooch, Jan 3, 2005
    #5
  6. Neo

    Richard Bos Guest

    "gooch" <> wrote:

    [ Using Google-Broken-Beta is not an excuse not to show any context.
    Learn to use it to quote properly or get a real newsreader. Context
    reinstated. ]

    > "Neo" <> wrote:
    >
    > > if I change the declaration above as :
    > >
    > > int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with
    > > unspecified bounds
    > > int arr[10];
    > > p = &arr;
    > > for(i=0; i <= 12; i++){
    > > *((*p) + i) = i;
    > > printf("%d\n", p[0]);
    > > }
    > >
    > > compiler error!
    > > what's the use of array index in the above declaration?
    > > as i can go upto 12 or more...


    > You can index up to whatever value you want. p[1000] is fine. The
    > result is going to be undefined.


    I don't see how you can write those sentences together. The result of
    p[10] and over are indeed going to be undefined, which is exactly why
    such indices are _not_ fine.

    > In most cases you would get a seg fault but that may not be the case.


    If you're lucky, you'll get a segfault. If you're unlucky, you won't see
    the segfault, but your customer will. If you're _really_ unlucky,
    neither of you will get a segfault, but your program will slowly
    scribble over all your customer's data, and he'll sue you. Don't run
    over the end of your arrays, not even when you think "it'll be safe,
    because you'll get a segfault anyway".

    Richard
    Richard Bos, Jan 3, 2005
    #6
  7. Neo

    gooch Guest

    "I don't see how you can write those sentences together. ....."

    I am not saying it is a good thing or that you should do it, only that
    it is not a legal operation.

    "If you're lucky, you'll get a segfault. ....."

    Again I am not suggesting he assume a segfault will occur, only that he
    needs to do the bounds checking himself.
    gooch, Jan 3, 2005
    #7
  8. On 3 Jan 2005 10:19:39 -0800, in comp.lang.c , "gooch"
    <> wrote:

    (contextless stuff)

    please read the VERY FIRST THING that richard said in his last post to you.

    --
    Mark McIntyre
    CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

    ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
    Mark McIntyre, Jan 3, 2005
    #8
  9. "gooch" <> writes:
    > You can index up to whatever value you want. p[1000] is fine. The
    > result is going to be undefined. In most cases you would get a seg
    > fault but that may not be the case. You have to do the bounds checking
    > yourself.


    (I presume p is an array with fewer than 1001 elements.)

    p[1000] is not "fine" in any sense of the word. It is a serious error
    that the implementation is not required to diagnose. This can
    sometimes have the same visible results as something that's perfectly
    legal, but the distinction is critical.

    Incidentally, it's not true that "in most cases you would get a seg
    fault". Attempting to access an array beyond its bounds is very
    likely to refer to some other variable in your program, with
    unpredictable results.

    Your overall point, that you have to do your own bounds checking
    because the implementation won't do it for you, is quite correct; I'm
    just (over)reacting to your use of the word "fine".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 3, 2005
    #9
  10. Neo

    Stan Milam Guest

    Jack Klein wrote:

    > On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <>
    > wrote in comp.lang.c:
    >
    >
    >>Hi Folks,
    >>
    >>
    >>#include<stdio.h>
    >>int main()
    >>{
    >> int (*p)[10];
    >> int arr[10];
    >> int i;
    >>
    >> p = arr; /* <-- compiler warning */

    >
    >
    > The name of an array in an expression, other than when it is the
    > operand of the 'sizeof' or '&' operators, is converted to a pointer to
    > its first element. So in the statement above, you are assigning the
    > address of an int (arr[0]) to a pointer to an array. But arr[0] is an
    > int, not an array of ints.
    >
    > Replace with:
    >
    > p = &arr;
    >
    >
    >> for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    >> *((*p) + i) = i;
    >>
    >> printf("%d\n", p[0]);
    >> }
    >>
    >> return 0;
    >>}
    >>
    >>In the above program compiler is giving following warning
    >>
    >>$gcc pointer2array.c
    >>pointer2array.c: In function `main':
    >>pointer2array.c:8: warning: assignment from incompatible pointer type
    >>
    >>Why the warning?
    >>
    >>O'kay and what is the use of int (*p)[10] type of declaration ?
    >>Does the compiler perform any check on the array bounds?
    >>lets say if i declare int arr[12]...


    Okay, both of you are mistaken. int (*p)[10] is declaring an array of
    10 pointers to function that return integers. Not quite the same thing
    as either of you are talking about.

    --
    Regards,
    Stan Milam.
    -----------------------------------------------------------------------------
    Vita Brevis. Carpe Guitarum! - Jamie Kinscherff
    -----------------------------------------------------------------------------
    Stan Milam, Jan 4, 2005
    #10
  11. Neo

    Neo Guest

    "Stan Milam" <> wrote in message
    news:5EpCd.10716$...
    > Jack Klein wrote:
    >
    >> On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <>
    >> wrote in comp.lang.c:
    >>
    >>
    >>>Hi Folks,
    >>>
    >>>
    >>>#include<stdio.h>
    >>>int main()
    >>>{
    >>> int (*p)[10];
    >>> int arr[10];
    >>> int i;
    >>>
    >>> p = arr; /* <-- compiler warning */

    >>
    >>
    >> The name of an array in an expression, other than when it is the
    >> operand of the 'sizeof' or '&' operators, is converted to a pointer to
    >> its first element. So in the statement above, you are assigning the
    >> address of an int (arr[0]) to a pointer to an array. But arr[0] is an
    >> int, not an array of ints.
    >>
    >> Replace with:
    >>
    >> p = &arr;
    >>
    >>
    >>> for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    >>> *((*p) + i) = i;
    >>>
    >>> printf("%d\n", p[0]);
    >>> }
    >>>
    >>> return 0;
    >>>}
    >>>
    >>>In the above program compiler is giving following warning
    >>>
    >>>$gcc pointer2array.c
    >>>pointer2array.c: In function `main':
    >>>pointer2array.c:8: warning: assignment from incompatible pointer type
    >>>
    >>>Why the warning?
    >>>
    >>>O'kay and what is the use of int (*p)[10] type of declaration ?
    >>>Does the compiler perform any check on the array bounds?
    >>>lets say if i declare int arr[12]...

    >
    > Okay, both of you are mistaken. int (*p)[10] is declaring an array of 10
    > pointers to function that return integers. Not quite the same thing as
    > either of you are talking about.
    >
    > --
    > Regards,
    > Stan Milam.
    > -----------------------------------------------------------------------------
    > Vita Brevis. Carpe Guitarum! - Jamie Kinscherff
    > -----------------------------------------------------------------------------


    pointers to function???
    hmm.... its a pointer to arrary of 10 INTs!
    -Neo
    Neo, Jan 4, 2005
    #11
  12. Neo

    -berlin.de Guest

    Stan Milam <> wrote:
    > Okay, both of you are mistaken. int (*p)[10] is declaring an array of
    > 10 pointers to function that return integers. Not quite the same thing
    > as either of you are talking about.


    Sorry, but no.

    int ( *p )[ 10 ];

    is a pointer to an array of 10 ints. The parentheses here are needed to
    distinguish it from

    int *p[ 10 ];

    which would be an array of 10 pointers to int. An array of 10 pointers
    to functions that return int would be

    int ( *p[ 10 ] )( );

    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
    -berlin.de, Jan 4, 2005
    #12
  13. On Mon, 03 Jan 2005 12:44:42 +0530, Neo wrote:

    > Hi Folks,
    >
    >
    > #include<stdio.h>
    > int main()
    > {
    > int (*p)[10];
    > int arr[10];
    > int i;
    >
    > p = arr; /* <-- compiler warning */
    > for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
    > *((*p) + i) = i;
    >
    > printf("%d\n", p[0]);
    > }
    >
    > return 0;
    > }
    >
    > In the above program compiler is giving following warning
    >
    > $gcc pointer2array.c
    > pointer2array.c: In function `main':
    > pointer2array.c:8: warning: assignment from incompatible pointer type
    >
    > Why the warning?


    Becuase you are trying to assign a value of type int * to a variable of
    type int (*)[10]. C doesn't support implicit conversion between these
    types. You could write

    p = &arr;

    but there isn't anything obvious to be gained over defining p as int *.

    > O'kay and what is the use of int (*p)[10] type of declaration ?


    You could use this in something like the following

    int arr2[5][10];
    int (*p2)[10] = arr2;

    Then accessing p2[x][y] will access the element arr2[x][y]

    > Does
    > the compiler perform any check on the array bounds? lets say if i
    > declare int arr[12]...


    C doesn't require any sort of bounds checking from the compiler, and most
    don't attempt to.

    Lawrence
    Lawrence Kirby, Jan 4, 2005
    #13
  14. Neo

    S.Tobias Guest

    Mark McIntyre <> wrote:
    > On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
    > <> wrote:


    > >if I change the declaration above as :
    > >
    > > int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds
    > >
    > >compiler error!


    > yes, its an error


    IMHO I think you're wrong here. `p' is simply a pointer to incomplete type
    ("array of int of unknown size").

    The OP probably hadn't noticed that the error was at different line:
    printf("%d\n", p[0]); //error
    Exactly, the offending expression is p[0], because, it gets translated
    to:
    *(p + 0)
    in which the summation cannot be evaluated because `*p' has an incomplete
    type (however I fail to explain exactly why, because this expression doesn't
    seem to violate any constraints at the "+" operator; could anyone help?).

    The above expression can be corrected with:
    (*p);
    This is interesting, because we seem to apply indirection operator to
    pointer to incomplete type (again, this is not a constraint violation,
    however it doesn't work with pointers to incomplete struct type; could
    someone help explain this please?); but here lvalue `*p', which is
    of "array of int" type, is converted to "pointer to int" and points
    to its first element, essentially same location as the array itself;
    this rule seems to take precedence.


    > >what's the use of array index in the above declaration?


    Type `int[]' is compatible with `int[10]' and `int[20]',
    so `p' could be assigned an address of objects defined as:
    int a[15];
    int b[80];
    double d[10]; //except this object
    p = &a;
    p = &b;
    p = &d; //error
    However, since `p' is a pointer to incomplete type, no arithmetic or
    comparisons can be made with it.
    I think one can describe `p' as a generic pointer to "arrays of int".
    I don't know if it could be more useful than that.

    > >as i can go upto 12 or more...


    > only by invoking undefined behaviour....


    Yes.

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
    S.Tobias, Jan 7, 2005
    #14
  15. On Fri, 07 Jan 2005 22:31:16 +0000, S.Tobias wrote:

    > Mark McIntyre <> wrote:
    >> On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
    >> <> wrote:

    >
    >> >if I change the declaration above as :
    >> >
    >> > int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds
    >> >
    >> >compiler error!

    >
    >> yes, its an error

    >
    > IMHO I think you're wrong here. `p' is simply a pointer to incomplete type
    > ("array of int of unknown size").
    >
    > The OP probably hadn't noticed that the error was at different line:
    > printf("%d\n", p[0]); //error
    > Exactly, the offending expression is p[0], because, it gets translated
    > to:
    > *(p + 0)
    > in which the summation cannot be evaluated because `*p' has an incomplete
    > type (however I fail to explain exactly why, because this expression doesn't
    > seem to violate any constraints at the "+" operator; could anyone help?).


    In both C90 and C99 the + operator requires a pointer operand to have a
    pointer to an object type; an incomplete type is not an object type. This
    is a constraint.

    Lawrence
    Lawrence Kirby, Jan 11, 2005
    #15
  16. Neo

    S.Tobias Guest

    Lawrence Kirby <> wrote:
    > On Fri, 07 Jan 2005 22:31:16 +0000, S.Tobias wrote:


    > > *(p + 0)
    > > in which the summation cannot be evaluated because `*p' has an incomplete
    > > type (however I fail to explain exactly why, because this expression doesn't
    > > seem to violate any constraints at the "+" operator; could anyone help?).


    > In both C90 and C99 the + operator requires a pointer operand to have a
    > pointer to an object type; an incomplete type is not an object type. This
    > is a constraint.


    Ah yes, thank you very much! I failed to check and understand the difference
    between object and incomplete types (I thought object types were divided
    into complete and incomplete; why is a long story).

    I hope the rest of my previous analysis is mostly correct.


    I think two things yet need an explanation.

    1.
    # 6.5.3.2 Address and indirection operators
    # Constraints
    # [...]
    # 2 The operand of the unary * operator shall have pointer type.
    a) This clearly allows pointers to incomplete types; why aren't they
    generally forbidden?
    b) Why can't I apply `*' to pointer to incomplete struct type?
    struct notdefinedhereyet *p; //ptr to incomplete type
    *p; //compiler refuses to generate code here, why?

    2.
    # 6.5.8 Relational operators
    # [...]
    # Constraints
    # 2 One of the following shall hold:
    # -- both operands have real type;
    # -- both operands are pointers to qualified or unqualified
    # versions of compatible object types; or
    # -- both operands are pointers to qualified or unqualified
    # versions of compatible incomplete types.
    Why is one allowed to compare pointers either when both are pointers
    to complete or both are pointers to incomplete compatible types?
    Why a pair one being a pointer to complete and the other to incomplete
    version of compatible type is excluded?

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
    S.Tobias, Jan 12, 2005
    #16
  17. On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:

    ....

    > I think two things yet need an explanation.
    >
    > 1.
    > # 6.5.3.2 Address and indirection operators
    > # Constraints
    > # [...]
    > # 2 The operand of the unary * operator shall have pointer type.
    > a) This clearly allows pointers to incomplete types; why aren't they
    > generally forbidden?


    Some reasons

    1. &*p is valid. This might appear for example in macro expansions

    2. Consider

    extern int (*pa)[];
    int *p = *pa;


    > b) Why can't I apply `*' to pointer to incomplete struct type?
    > struct notdefinedhereyet *p; //ptr to incomplete type
    > *p; //compiler refuses to generate code here, why?


    Don't know, looks OK to me, as long as p points at a suitable object.

    > 2.
    > # 6.5.8 Relational operators
    > # [...]
    > # Constraints
    > # 2 One of the following shall hold:
    > # -- both operands have real type;
    > # -- both operands are pointers to qualified or unqualified
    > # versions of compatible object types; or
    > # -- both operands are pointers to qualified or unqualified
    > # versions of compatible incomplete types.
    > Why is one allowed to compare pointers either when both are pointers
    > to complete or both are pointers to incomplete compatible types?
    > Why a pair one being a pointer to complete and the other to incomplete
    > version of compatible type is excluded?


    Very good question. If nobody comes up with an answer maybe ask on
    comp.std.c.

    Lawrence
    Lawrence Kirby, Jan 13, 2005
    #17
  18. Neo

    S.Tobias Guest

    Lawrence Kirby <> wrote:
    > On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:


    > > # 2 The operand of the unary * operator shall have pointer type.
    > > a) This clearly allows pointers to incomplete types; why aren't they
    > > generally forbidden?


    Dereferencing a pointer yields an lvalue. Since incomplete type
    doesn't fully describe an object, the result can't be a "good lvalue".
    My personal feeling was that it would be more natural that
    by default pointers to incomplete types be forbidden, except
    in special cases.

    > 1. &*p is valid. This might appear for example in macro expansions


    > extern int (*pa)[];
    > int *p = *pa;


    Yes, these are those special cases, in which the dereferenced pointer
    does not denote an lvalue (1. `*' is canceled by `&'; 2. result is
    immediately converted to another type).


    > > b) Why can't I apply `*' to pointer to incomplete struct type?
    > > struct notdefinedhereyet *p; //ptr to incomplete type
    > > *p; //compiler refuses to generate code here, why?


    > Don't know, looks OK to me, as long as p points at a suitable object.


    > > Why is one allowed to compare pointers either when both are pointers
    > > to complete or both are pointers to incomplete compatible types?
    > > Why a pair one being a pointer to complete and the other to incomplete
    > > version of compatible type is excluded?


    > Very good question. If nobody comes up with an answer maybe ask on
    > comp.std.c.


    Thank you. I'll ask all of these questions again in c.s.c. in a few
    days (if nobody...).

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
    S.Tobias, Jan 13, 2005
    #18
  19. On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:

    > Lawrence Kirby <> wrote:
    >> On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:

    >
    >> > # 2 The operand of the unary * operator shall have pointer type.
    >> > a) This clearly allows pointers to incomplete types; why aren't they
    >> > generally forbidden?

    >
    > Dereferencing a pointer yields an lvalue.


    Dereferencing a pointer can yield an lvalue. However the text of the
    standard looks terminally broken in this respect. I should probably check
    defects.

    Essentially the problem is that the concept of lvalue is used in
    constraint specifications (e.g. 6.5.16p2) which means that it is a
    property that must be determinable at compile time, i.e. from static
    analysis of the source code. C99 6.5.3.2p4 says

    "The unary * operator denotes indirection. If the operand points to a
    function, the result is a function designator; if it points to an object,
    the result is an lvalue designating the object."

    This is a specification for lvalue-ness based on a runtime property i.e.
    whether the pointer points at an object or not, which makes it unworkable.
    C99 6.3.2.1 says:

    "An lvalue is an expression with an object type or an incomplete type
    other than void;"

    Note specifically that lvalues can have an incomplete type which is good
    and correct. This of course has its own problems, apparently saying that
    the expression 42 is an lvalue.

    > Since incomplete type
    > doesn't fully describe an object, the result can't be a "good lvalue".


    But it can be an lvalue. For example

    extern int a[];

    a[0] = 1;

    Here a has an incomplete type but because it is an lvalue is is still
    converted to a pointer to its first element in an expression.

    > My personal feeling was that it would be more natural that
    > by default pointers to incomplete types be forbidden, except
    > in special cases.


    I see no reason for this. If you allow void * you have to deal with
    pointers to incomplete types one way or another. Using pointers to
    incomplete structure types is a valid and important approach for
    abstraction and information hiding.

    >> 1. &*p is valid. This might appear for example in macro expansions

    >
    >> extern int (*pa)[];
    >> int *p = *pa;

    >
    > Yes, these are those special cases, in which the dereferenced pointer
    > does not denote an lvalue (1. `*' is canceled by `&'; 2. result is
    > immediately converted to another type).


    In the 2nd case *pa must be an lvalue for this to work.

    ....

    Lawrence
    Lawrence Kirby, Jan 14, 2005
    #19
  20. Lawrence Kirby <> writes:
    [...]
    > Dereferencing a pointer can yield an lvalue. However the text of the
    > standard looks terminally broken in this respect. I should probably check
    > defects.


    Yes, the standard's definition of "lvalue" is badly broken.

    C90 6.2.2.1 says:

    An _lvalue_ is an expression (with an object type or an incomplete
    type other than void) that designates an object.

    The problem with this definition is that, strictly speaking, you can't
    determine at compilation time whether something is an lvalue or not.
    Given a declaration

    int *ptr;

    the expression *ptr designates an object only if current the value of
    ptr is non-null. Presumably the intent was that *ptr is an lvalue
    regardless of the current value of ptr (and evaluating it invokes
    undefined behavior if ptr happens to be null), but the definition
    doesn't capture that intent.

    C99 6.3.2.1 corrects this problem, but introduces a bigger one:

    An _lvalue_ is an expression with an object type or an incomplete
    type other than void; if an lvalue does not designate an object
    when it is evaluated, the behavior is undefined.

    This captures the idea that "*ptr" is an lvalue even if ptr==NULL --
    but it also implies that 42 is an lvalue (because it's an expression
    with an object type). It no longer says that an lvalue denotes an
    object (which is what the concept of "lvalue" is all about), it merely
    threatens undefined behavior if it doesn't.

    The standard needs to say that an lvalue is an expression that either
    denotes an object, or would denote an object if its subexpressions had
    the right values. The trick is expressing this in sufficiently
    rigorous standardese.

    I raised this issue on comp.std.c a few months ago, but the discussion
    wasn't productive.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 14, 2005
    #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. S300
    Replies:
    4
    Views:
    21,971
    Roedy Green
    Aug 19, 2003
  2. Schnoffos
    Replies:
    2
    Views:
    1,199
    Martien Verbruggen
    Jun 27, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,615
    Old Wolf
    Jan 20, 2004
  4. arun
    Replies:
    8
    Views:
    434
    Dave Thompson
    Jul 31, 2006
  5. Alain Spineux
    Replies:
    6
    Views:
    621
    Eric Sosman
    May 17, 2011
Loading...

Share This Page