address of a struct or a pointer to a struct?

Discussion in 'C Programming' started by Johs32, Mar 2, 2006.

  1. Johs32

    Johs32 Guest

    I have a struct "my_struct" and a function that as argument takes a pointer
    to this struct:

    struct my_struct{
    struct my_struct *new;
    };

    void my_func(struct my_struct *new);

    I have read that there is no difference between giving this function a
    pointer to a struct or the address of a struct:

    1) passing a pointer to a struct:
    struct my_struct *pp;
    my_func(pp);


    2) passing an address of a struct
    struct my_struct new;
    my_func(&new);


    is it true that both of the above options are correct?



    Another thing I have been told that if I do:

    struct my_struct *p;
    p->new = NULL;

    I should first malloc "p" because a pointer should be initialized before
    using "->", but is that not what p->new = NULL does (initialising new) or
    do I first need to malloc "p" before I initialize new?
    Johs32, Mar 2, 2006
    #1
    1. Advertising

  2. Johs32 wrote:

    > I have a struct "my_struct" and a function that as argument takes a
    > pointer to this struct:
    >
    > struct my_struct{
    > struct my_struct *new;
    > };
    >
    > void my_func(struct my_struct *new);
    >
    > I have read that there is no difference between giving this function a
    > pointer to a struct or the address of a struct:
    >
    > 1) passing a pointer to a struct:
    > struct my_struct *pp;
    > my_func(pp);
    >
    > 2) passing an address of a struct
    > struct my_struct new;
    > my_func(&new);
    >
    > is it true that both of the above options are correct?


    They are both syntactically correct. Semantically, they're only
    identical if pp == &new.

    > Another thing I have been told that if I do:
    >
    > struct my_struct *p;
    > p->new = NULL;
    >
    > I should first malloc "p" because a pointer should be initialized
    > before using "->", but is that not what p->new = NULL does
    > (initialising new) or do I first need to malloc "p" before I
    > initialize new?


    Structure element `new` can only be initialised if it exists. It will
    only exist if the structure it belongs to exists. That will only happen
    if you allocate memory for it. Once you do that, you can access the
    structure and its members, and assign values to them.

    I guess you'd have been slightly less confused if you didn't use `new`
    for a few different things above.

    --
    BR, Vladimir

    "Are [Linux users] lemmings collectively jumping off of the cliff of
    reliable, well-engineered commercial software?"
    (By Matt Welsh)
    Vladimir S. Oka, Mar 2, 2006
    #2
    1. Advertising

  3. Johs32

    Eric Sosman Guest

    Johs32 wrote On 03/02/06 16:27,:
    > I have a struct "my_struct" and a function that as argument takes a pointer
    > to this struct:
    >
    > struct my_struct{
    > struct my_struct *new;
    > };
    >
    > void my_func(struct my_struct *new);
    >
    > I have read that there is no difference between giving this function a
    > pointer to a struct or the address of a struct:
    >
    > 1) passing a pointer to a struct:
    > struct my_struct *pp;
    > my_func(pp);


    This is fine, provided `pp' has been given a valid
    value before you try to pass it to my_func(). That is,
    you must set `pp' to point to a `struct my_struct' object
    or you must set it to NULL.

    This is really no different than with non-pointer
    variables:

    double d;
    your_func(d);

    You must give `d' a valid `double' value before trying
    to call the function.


    > 2) passing an address of a struct
    > struct my_struct new;
    > my_func(&new);


    This is fine. `struct my_struct new;' allocates
    memory for the object, and `&new' produces a pointer
    to that memory.

    > is it true that both of the above options are correct?


    Yes (assuming a value is supplied in the first).
    The difference is very much like the difference between

    int variable = 6 * 7;
    their_func(variable);

    and

    their_func(42);

    > Another thing I have been told that if I do:
    >
    > struct my_struct *p;
    > p->new = NULL;
    >
    > I should first malloc "p" because a pointer should be initialized before
    > using "->", but is that not what p->new = NULL does (initialising new) or
    > do I first need to malloc "p" before I initialize new?


    You have confused yourself by using the name `new'
    to mean three different things:

    - It is the name of one of the elements contained
    inside each `struct my_struct' object, and

    - It is the name you have used for one such object, and

    - It is the name of the formal parameter of the
    my_func() function.

    The name is the same, but the three things it names are
    different. You may know several people called "Leo," a
    name that is also used for one of the constellations and
    for thirteen different Roman Catholic Popes. That doesn't
    mean that your friend "Leo" is a collection of stars! I
    suggest that you try to use different names for different
    things, as far as is practical -- it will help to reduce
    confusion.

    You might also be confused by the fact that each
    `struct my_struct' contains a pointer to a `struct my_struct'
    object. There is nothing special about that inner pointer:
    it's just a pointer. It could perfectly well be a pointer
    to some completely different type of object -- it could just
    as well be a `double'. The point (sorry) is that you cannot
    get at that inner datum until you have a `struct my_struct'
    that holds it. Backing up one level, you cannot use `p' to
    get at that inner datum until you make sure `p' points to
    a `struct my_struct'. You can do that by using malloc() to
    obtain memory for the struct (and checking that it succeeded),
    or by setting `p' equal to `& a_struct_my_struct_variable',
    or by various other paths. In any event, you cannot use `p'
    to read or write the content of the struct until you first
    make sure `p' actually points to one.

    --
    Eric Sosman, Mar 2, 2006
    #3
  4. Johs32

    Johs32 Guest

    > You might also be confused by the fact that each
    > `struct my_struct' contains a pointer to a `struct my_struct'
    > object. There is nothing special about that inner pointer:
    > it's just a pointer. It could perfectly well be a pointer
    > to some completely different type of object -- it could just
    > as well be a `double'. The point (sorry) is that you cannot
    > get at that inner datum until you have a `struct my_struct'
    > that holds it. Backing up one level, you cannot use `p' to
    > get at that inner datum until you make sure `p' points to
    > a `struct my_struct'. You can do that by using malloc() to
    > obtain memory for the struct (and checking that it succeeded),
    > or by setting `p' equal to `& a_struct_my_struct_variable',
    > or by various other paths. In any event, you cannot use `p'
    > to read or write the content of the struct until you first
    > make sure `p' actually points to one.
    >



    Ok if I try to remove the confusion:

    struct my_struct{
    struct my_struct *data;
    };

    void my_func(struct my_struct *arg)
    {
    if(arg != NULL) {
    arg->data = NULL;
    }
    }


    int main(void) {
    struct my_struct new_data;
    my_func(&new_data);

    return 0;

    }

    In my_func I initialize the pointer "data" in my_struct to NULL, I guees
    this is legal since I made sure to "malloc" new_data by:

    struct my_struct new_data;

    in main.

    But is the only way a pointer can "survive" a function call not that I
    malloc it?

    In my_func I only initialize the "data" pointer to NULL, but should I not
    first malloc it and then set it to NULL, to make sure that I can use the
    "data" pointer in the my_struct struct, after the call to my_func?
    Johs32, Mar 3, 2006
    #4
  5. Johs32 wrote:
    > Ok if I try to remove the confusion:
    >
    > struct my_struct{
    > struct my_struct *data;
    > };
    >
    > void my_func(struct my_struct *arg)
    > {
    > if(arg != NULL) {
    > arg->data = NULL;
    > }
    > }


    Here, you pass a pointer to a struct that's presumably allocated
    outside `my_func`. As I see below, you actually pass the address of a
    variable, so the space is aleady allocated for your structure.

    You not only do not have to allocate it again in `my_func` but doing
    that would achieve absolutely nothing, or at least not what you seem to
    want. You'd be initialising `data` member of newly allocated structure.
    If you then do not return its address to the caller, and use it, your
    changes are lost (BTW, you'd have also created a memory leak).

    Note: if you manage to pass an unitialised pointer to `my_func` you're
    running the risk of trying to dereference garbage pointer
    (uninitialised pointers are not guaranteed to be NULL). This, you have
    to check before calling `my_func`.

    > int main(void) {
    > struct my_struct new_data;
    > my_func(&new_data);


    As per note above: If you use `my_func` like this, it's guaranteed to
    get a valid, non-NULL, address.

    > return 0;
    >
    > }
    >
    > In my_func I initialize the pointer "data" in my_struct to NULL, I guees
    > this is legal since I made sure to "malloc" new_data by:
    >
    > struct my_struct new_data;


    This does not "malloc" new data. This declares a variable, and the
    compiler will make sure it's allocated some space once `main` is
    called. You "malloc" by:

    struct my_struct *p;

    p = malloc(sizeof *p); /* do NOT cast result of malloc! */
    if (p == NULL)
    /* failed, do something about it */;
    else
    my_func(p);


    > But is the only way a pointer can "survive" a function call not that I
    > malloc it?
    >
    > In my_func I only initialize the "data" pointer to NULL, but should I not
    > first malloc it and then set it to NULL, to make sure that I can use the
    > "data" pointer in the my_struct struct, after the call to my_func?


    See above.
    Vladimir S. Oka, Mar 3, 2006
    #5
  6. On Fri, 03 Mar 2006 08:48:51 +0100, Johs32 <> wrote:

    >Ok if I try to remove the confusion:
    >
    >struct my_struct{
    > struct my_struct *data;
    >};
    >
    >void my_func(struct my_struct *arg)
    >{
    > if(arg != NULL) {
    > arg->data = NULL;
    > }
    >}
    >
    >
    >int main(void) {
    > struct my_struct new_data;
    > my_func(&new_data);
    >
    >return 0;
    >
    >}
    >
    >In my_func I initialize the pointer "data" in my_struct to NULL, I guees
    >this is legal since I made sure to "malloc" new_data by:
    >
    > struct my_struct new_data;


    No, this does not malloc anything. new_data is an automatic object of
    type struct my_struct. It exists for the life of main().

    >
    >in main.
    >
    >But is the only way a pointer can "survive" a function call not that I
    >malloc it?


    As a general rule, all the variables of main will survive all function
    calls and remain unchanged by the actions of the called function.
    There are some exceptions, such as the exit function, but they are
    details not related to your very basic question.

    >
    >In my_func I only initialize the "data" pointer to NULL, but should I not
    >first malloc it and then set it to NULL, to make sure that I can use the
    >"data" pointer in the my_struct struct, after the call to my_func?


    NO. If you assign data the value returned by malloc and the set it to
    NULL, you create an instant memory leak which is something that should
    almost always be avoided. data is a member of the structure new_data
    which is an automatic object in main. It existed before your function
    was called, continues to exist while your function is executing, and
    will exist after your function executes.

    You have hit on one of the exceptions mentioned earlier. If you pass
    the address of a local object to a function, that function can, by
    dereferencing the address, change the value stored in that local
    object. You passed &new_data and this allows your function to update
    new_data.data in main.

    Since your function set data to NULL, the only thing main can do with
    that value is test for it. main cannot dereference data since
    dereferencing a NULL pointer invokes undefined behavior. The pointer
    is essentially useless until it is initialized to point to some usable
    area of memory.

    If you want main to be able to use the result of your function as a
    valid memory address, your function should assign data the value
    returned by malloc and forget about setting it to NULL.


    Remove del for email
    Barry Schwarz, Mar 12, 2006
    #6
    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. beetle
    Replies:
    2
    Views:
    874
    beetle
    Jan 25, 2005
  2. Zero
    Replies:
    16
    Views:
    633
    Barry Schwarz
    Nov 19, 2005
  3. jimjim
    Replies:
    16
    Views:
    813
    Jordan Abel
    Mar 28, 2006
  4. Stanley Rice

    Address of array && address of pointer to array

    Stanley Rice, Sep 14, 2011, in forum: C Programming
    Replies:
    33
    Views:
    1,105
    Keith Thompson
    Sep 20, 2011
  5. aleksa

    Struct pointer vs. struct array pointer

    aleksa, Feb 20, 2013, in forum: C Programming
    Replies:
    16
    Views:
    443
    Shao Miller
    Feb 20, 2013
Loading...

Share This Page