address of a struct or a pointer to a struct?

J

Johs32

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?
 
V

Vladimir S. Oka

Johs32 said:
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)
 
E

Eric Sosman

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.
 
J

Johs32

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?
 
V

Vladimir S. Oka

Johs32 said:
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.
 
B

Barry Schwarz

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top