whats wrong with this pointer operation?

Discussion in 'C Programming' started by =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Apr 20, 2006.

  1. Hi,

    "C primer plus" p.382:

    Suppose we have this declaration:

    int (*pa)[3];
    int ar1[2][3];
    int ar2[3][2];
    int **p2;


    Then this is okay:
    pa = ar1; // both pointer-to-int[3]


    But these are not:
    pa = ar2; // why not?
    p2 = ar2; // why not?



    ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
    pointer-to-int-array).

    And pa must be a pointer to int[3]-array... So in my opinion pa = ar2
    should work but the book says "not valid"...? I also think that p2 = ar2
    should work, but that seems wrong according to the book?



    Best regards / Med venlig hilsen
    Martin Jørgensen

    --
    ---------------------------------------------------------------------------
    Home of Martin Jørgensen - http://www.martinjoergensen.dk
     
    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Apr 20, 2006
    #1
    1. Advertising

  2. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    pinkfog Guest

    Martin Jørgensen wrote:
    > Hi,
    >
    > "C primer plus" p.382:
    >
    > Suppose we have this declaration:
    >
    > int (*pa)[3];

    you can give a example to understand it.This expression means:
    an 2_D array: int* pa_0 ,int * pa_1 ,int* pa_2 ,that is to say: in the
    2-D array form ,there are integers of size_t rows and 3 colums .
    > int ar1[2][3];
    > int ar2[3][2];
    > int **p2;

    So ar1: 2 rows and 3 colums
    ar2: 3 rows and 2 colums
    p2: unknown size
    >
    > Then this is okay:
    > pa = ar1; // both pointer-to-int[3]


    Right. The assignment makes pa a 2*3 2_D array.
    >
    >
    > But these are not:
    > pa = ar2; // why not?
    > p2 = ar2; // why not?
    >


    Wrong. ar2 and pa are not of the same size.
    >
    > ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
    > pointer-to-int-array).
    >
    > And pa must be a pointer to int[3]-array... So in my opinion pa = ar2
    > should work but the book says "not valid"...? I also think that p2 = ar2
    > should work, but that seems wrong according to the book?

    Hope this can help a little.
    ----------------------pinkfog-----------------------
     
    pinkfog, Apr 20, 2006
    #2
    1. Advertising

  3. Martin Jørgensen <> writes:
    > "C primer plus" p.382:
    >
    > Suppose we have this declaration:
    >
    > int (*pa)[3];
    > int ar1[2][3];
    > int ar2[3][2];
    > int **p2;
    >
    >
    > Then this is okay:
    > pa = ar1; // both pointer-to-int[3]


    Right. ar1 is an array[2] of array[3] of int; it decays to a pointer
    to array[3] of int. Since pa is explicitly pointer to array[3] of
    int, the types match.

    > But these are not:
    > pa = ar2; // why not?
    > p2 = ar2; // why not?
    >
    > ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
    > pointer-to-int-array).


    No. Arrays are not pointers. Pointers are not arrays. There is no
    pointer-to-pointer here.

    The declaration
    int ar2[3][2];
    declares ar2 as an array[3] of array[2] of int. The memory allocated
    for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
    ar2, in most contexts, decays to a pointer to array[2] of int; this
    is a pointer value, not a pointer object.

    This declaration does *not* create a pointer-to-pointer. No space is
    allocated for any pointer object. A pointer-to-pointer and a
    pointer-to-array are two different things; neither may be converted to
    the other. A pointer *value* may be created when the name ar2 is used
    in an expression, but only a pointer to array[2] of int, not any kind
    of pointer-to-pointer.

    In
    pa = ar2;
    pa is of type pointer to array[3] of int, and ar2 is of type array[3]
    of array[2] of int, which decays to pointer to array[2] of int.
    Though both sides are pointers to array of int, the types don't match
    because they're pointers to arrays of different lengths.

    In
    p2 = ar2;
    p2 is a pointer to pointer to int, and as we've seen, ar2 is not, and
    does not decay into, a pointer to pointer. Again, the types are
    incompatible.

    If you haven't already, read section 6 of the comp.lang.c FAQ,
    "Pointers and Arrays".

    --
    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, Apr 20, 2006
    #3
  4. Keith Thompson wrote:
    > Martin Jørgensen <> writes:
    >
    >>"C primer plus" p.382:
    >>
    >>Suppose we have this declaration:
    >>
    >>int (*pa)[3];
    >>int ar1[2][3];
    >>int ar2[3][2];
    >>int **p2;
    >>
    >>
    >>Then this is okay:
    >>pa = ar1; // both pointer-to-int[3]

    >
    >
    > Right. ar1 is an array[2] of array[3] of int; it decays to a pointer
    > to array[3] of int. Since pa is explicitly pointer to array[3] of
    > int, the types match.


    Uh, yes... I forgot to look at the column-size...

    >>But these are not:
    >>pa = ar2; // why not?
    >>p2 = ar2; // why not?
    >>
    >>ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
    >>pointer-to-int-array).

    >
    >
    > No. Arrays are not pointers. Pointers are not arrays. There is no
    > pointer-to-pointer here.


    Ofcourse...

    > The declaration
    > int ar2[3][2];
    > declares ar2 as an array[3] of array[2] of int. The memory allocated
    > for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
    > ar2, in most contexts, decays to a pointer to array[2] of int; this
    > is a pointer value, not a pointer object.


    Thanks a lot... I just have to make sure: What exactly do you mean by:

    1) Pointer value

    2) Pointer object

    What's the difference? C isn't "object-oriented" as in C++ so I just
    want to make sure I understand the difference...

    > This declaration does *not* create a pointer-to-pointer. No space is
    > allocated for any pointer object. A pointer-to-pointer and a
    > pointer-to-array are two different things; neither may be converted to
    > the other. A pointer *value* may be created when the name ar2 is used
    > in an expression, but only a pointer to array[2] of int, not any kind
    > of pointer-to-pointer.


    Thanks... Makes sense.

    > In
    > pa = ar2;
    > pa is of type pointer to array[3] of int, and ar2 is of type array[3]
    > of array[2] of int, which decays to pointer to array[2] of int.


    Sounds to me like: I've read something about that there is a similarity
    between declaring array[3][2] and declaring array[][2] in a function
    header...

    Is that what you mean by "decaying into"?

    > Though both sides are pointers to array of int, the types don't match
    > because they're pointers to arrays of different lengths.


    It's only the column-size that must match, isn't it?

    > In
    > p2 = ar2;
    > p2 is a pointer to pointer to int, and as we've seen, ar2 is not, and
    > does not decay into, a pointer to pointer. Again, the types are
    > incompatible.
    >
    > If you haven't already, read section 6 of the comp.lang.c FAQ,
    > "Pointers and Arrays".


    I think I've read it a couple of times... But I just forgot something
    which I now remember...

    It isn't that hard for me to understand... That's why I only got a few
    comments here - I agree with what you wrote, after reading it...


    Best regards / Med venlig hilsen
    Martin Jørgensen

    --
    ---------------------------------------------------------------------------
    Home of Martin Jørgensen - http://www.martinjoergensen.dk
     
    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Apr 20, 2006
    #4
  5. On Thu, 20 Apr 2006 16:27:17 +0200, in comp.lang.c , Martin Jørgensen
    <> wrote:

    >Thanks a lot... I just have to make sure: What exactly do you mean by:
    >
    >1) Pointer value
    >
    >2) Pointer object


    int x=3;

    x is an int object

    3 is its int value

    Same thing with pointers.

    >Sounds to me like: I've read something about that there is a similarity
    >between declaring array[3][2] and declaring array[][2] in a function
    >header...
    >
    >Is that what you mean by "decaying into"?


    No, but its related.
    When an array is passed to a function, it is "decayed" into a pointer
    to its first element. Inside the function, there is no array, only the
    pointer.
    The example you give is a consequence of this. Since the array decays
    into a pointer, there is no use declaring its (first) dimension.


    >> Though both sides are pointers to array of int, the types don't match
    >> because they're pointers to arrays of different lengths.

    >
    >It's only the column-size that must match, isn't it?


    Please don't think of it as columns and rows - its not like that. What
    will you do when you get to 3, 4 or 5 dimensions?

    And AFAIK the types will only match if all dimensions match.

    Mark McIntyre
    --
    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
     
    Mark McIntyre, Apr 20, 2006
    #5
  6. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    Default User Guest

    Martin Jørgensen wrote:

    > Keith Thompson wrote:
    > >Martin Jørgensen <> writes:
    > >
    > > > "C primer plus" p.382:
    > > >
    > > > Suppose we have this declaration:
    > > >
    > > > int (*pa)[3];
    > > > int ar1[2][3];
    > > > int ar2[3][2];
    > > > int **p2;
    > > >
    > > >
    > > > Then this is okay:
    > > > pa = ar1; // both pointer-to-int[3]

    > >
    > >
    > > Right. ar1 is an array[2] of array[3] of int; it decays to a
    > > pointer to array[3] of int. Since pa is explicitly pointer to
    > > array[3] of int, the types match.

    >
    > Uh, yes... I forgot to look at the column-size...
    >
    > > > But these are not:
    > > > pa = ar2; // why not?
    > > > p2 = ar2; // why not?
    > > >
    > > > ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
    > > > pointer-to-int-array).

    > >
    > >
    > > No. Arrays are not pointers. Pointers are not arrays. There is no
    > > pointer-to-pointer here.

    >
    > Ofcourse...
    >
    > > The declaration
    > > int ar2[3][2];
    > > declares ar2 as an array[3] of array[2] of int. The memory
    > > allocated for it is enough to hold 3*2 int objects (6 *
    > > sizeof(int)). The name ar2, in most contexts, decays to a pointer
    > > to array[2] of int; this is a pointer value, not a pointer object.

    >
    > Thanks a lot... I just have to make sure: What exactly do you mean by:
    >
    > 1) Pointer value
    >
    > 2) Pointer object
    >
    > What's the difference? C isn't "object-oriented" as in C++ so I just
    > want to make sure I understand the difference...


    From the draft standard:

    3.15
    [#1] object
    region of data storage in the execution environment, the
    contents of which can represent values

    [#2] NOTE When referenced, an object may be interpreted as
    having a particular type; see 6.3.2.1.

    So pointer objects can hold pointer values.


    > Sounds to me like: I've read something about that there is a
    > similarity between declaring array[3][2] and declaring array[][2] in
    > a function header...


    The leftmost dimension isn't necessary in function declarations,
    because you can't pass arrays, only pointers to the first element.
    That's why you can have:

    void func(int *p);
    void func(int p[]);

    They both mean the same thing. In the case of a mult-dimension array,
    the first element is another array.

    > Is that what you mean by "decaying into"?


    In most contexts, the name of an array is converted to a pointer to the
    first element. Exceptions include with the array name is used with the
    sizeof operator or the address-of (&) operator.

    > > Though both sides are pointers to array of int, the types don't
    > > match because they're pointers to arrays of different lengths.

    >
    > It's only the column-size that must match, isn't it?


    Everything but the left-most dimension. So if it was a three-D array,
    the two right dimensions would have to match.



    Brian
     
    Default User, Apr 20, 2006
    #6
  7. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    pete Guest

    Mark McIntyre wrote:
    >
    > On Thu, 20 Apr 2006 16:27:17 +0200, in comp.lang.c , Martin Jørgensen
    > <> wrote:
    >
    > >Thanks a lot... I just have to make sure:
    > >What exactly do you mean by:
    > >
    > >1) Pointer value
    > >
    > >2) Pointer object

    >
    > int x=3;
    >
    > x is an int object
    >
    > 3 is its int value
    >
    > Same thing with pointers.


    (&x) is an example of a pointer value
    that is not a pointer object.

    --
    pete
     
    pete, Apr 20, 2006
    #7
  8. Martin Jørgensen <> writes:
    > Keith Thompson wrote:
    >> Martin Jørgensen <> writes:

    [...]
    >> The declaration
    >> int ar2[3][2];
    >> declares ar2 as an array[3] of array[2] of int. The memory allocated
    >> for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
    >> ar2, in most contexts, decays to a pointer to array[2] of int; this
    >> is a pointer value, not a pointer object.

    >
    > Thanks a lot... I just have to make sure: What exactly do you mean by:
    >
    > 1) Pointer value
    >
    > 2) Pointer object
    >
    > What's the difference? C isn't "object-oriented" as in C++ so I just
    > want to make sure I understand the difference...


    Right, the term "object" in C has nothing to do with "object-oriented"
    anything. The standard's definition of "object" is a "region of data
    storage in the execution environment, the contents of which can
    represent values" (C99 3.14).

    Loosely speaking, it's nearly the same thing as a variable. An object
    can also be a component of another object, or the chunk of memory
    allocated by malloc(). (The standard doesn't define the term
    "variable".)

    A value is the result of evaluating an expression. It isn't
    necessarily stored anywhere; it's a transient thing that exists only
    while the expression is being evaluated, unless it's stored in an
    object.

    An object name is an expression; the value of the expression is the
    value that was stored in the object.

    A pointer object is an object of pointer type; the value of a pointer
    object is a pointer value, also known as an address.

    (There's some controversy in this area. Some people feel strongly
    that the unadorned word "pointer" should refer only to a pointer
    object, never to a value -- but the standard, like it or not, talks
    about functions returning pointers. I usually try to avoid the issue
    by referring explicitly to pointer objects and pointer values.)

    >[...]


    >> In
    >> pa = ar2;
    >> pa is of type pointer to array[3] of int, and ar2 is of type array[3]
    >> of array[2] of int, which decays to pointer to array[2] of int.

    >
    > Sounds to me like: I've read something about that there is a
    > similarity between declaring array[3][2] and declaring array[][2] in a
    > function header...
    >
    > Is that what you mean by "decaying into"?


    No, that's something different (but related, I suppose).

    A function can't have a parameter of array type. You can declare
    something that *looks* like an array parameter:
    void foo(char param[]);
    but, because of a special-case rule, that's exactly the same as:
    void foo(char *param);
    The same is true if you specify the length of the aray:
    void foo(char param[42]);
    The length is just quietly ignored.

    The intent of the rule is to allow you to indicate that the argument
    is expected to be an array (which will decay to a pointer), but in my
    opinion this rule causes more problems than it solves.

    Your example:
    void bar(int array[3][2]);
    vs.
    void bar(int array[][2]);
    is just a special case of this, where the array's element type happens
    to be another array type.

    But when I used the phrase "decaying into", I was referring to the
    implicit conversion of array expressions to pointer type.

    In most contexts, an expression of array type (such as the name of a
    declared array object) is implicitly converted to a pointer to the
    array's first element. The exceptions are: (1) the argument to the
    "sizeof" operator, (2) the argument to the "&" operator, and (3) a
    string literal used in an initialize an array.

    >> Though both sides are pointers to array of int, the types don't match
    >> because they're pointers to arrays of different lengths.

    >
    > It's only the column-size that must match, isn't it?


    In this case, yes (of course the element type must match as well).
    But a better way to think about it is that the types must match, after
    any implicit conversions have been applied. A two-dimensional array
    is just an array of arrays. There are no special rules for
    multi-dimensional arrays; their behavior is determined entirely by the
    rules for one-dimensional arrays, including implicit conversions to
    pointers.

    --
    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, Apr 20, 2006
    #8
  9. Mark McIntyre <> writes:
    > On Thu, 20 Apr 2006 16:27:17 +0200, in comp.lang.c , Martin Jørgensen
    > <> wrote:

    [...]
    >>Sounds to me like: I've read something about that there is a similarity
    >>between declaring array[3][2] and declaring array[][2] in a function
    >>header...
    >>
    >>Is that what you mean by "decaying into"?

    >
    > No, but its related.
    > When an array is passed to a function, it is "decayed" into a pointer
    > to its first element. Inside the function, there is no array, only the
    > pointer.
    > The example you give is a consequence of this. Since the array decays
    > into a pointer, there is no use declaring its (first) dimension.


    Right. And this is just one case of a more general rule, having
    nothing to do with function calls. An expression of array type is (in
    most contexts) implicitly converted to a pointer to its first element.
    This applies whether it's a function argument, the right hand side of
    an assignment, or the operand of a "+" operator (with the exceptions
    that have already been mentioned several times in this thread).

    It even applies to the array indexing operator. For example:

    int arr[10];
    int x = arr[5];

    The indexing operator takes two operands, a pointer and an integer.
    If one of its operands is the name of an array, that operand is
    implicitly converted to a pointer. An indexing operator "x[y]" is by
    definition equivalent to "*(x+y)". It's most commonly used on arrays,
    of course, but that's just a special case; it's defined to work on
    pointers.

    --
    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, Apr 20, 2006
    #9
    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. Alexandre Martins

    Whats wrong with this provider ??

    Alexandre Martins, Aug 14, 2003, in forum: ASP .Net
    Replies:
    5
    Views:
    363
    Guenther Liebowitz
    Aug 14, 2003
  2. Dan

    whats wrong with this pointer?

    Dan, May 2, 2005, in forum: C Programming
    Replies:
    5
    Views:
    334
    =?iso-8859-1?q?Dag-Erling_Sm=F8rgrav?=
    May 2, 2005
  3. david ullua
    Replies:
    13
    Views:
    674
  4. raan
    Replies:
    2
    Views:
    456
  5. Buzz Lightyear
    Replies:
    10
    Views:
    1,136
    Alexander Bartolich
    Aug 12, 2009
Loading...

Share This Page