"basic" pointer question

J

Jonathan Bartlett

My questions are these:
1) Do I have to allocate space for the doubles lst_t, lst_vc, lst_ic
as well
as their pointers?

I think you are confusing issues. The malloc() statements in your post
ARE allocating the space for the doubles.

last_values *lst_ptr = malloc(sizeof(*lst_ptr));

[however, this should actually be size(last_values)]

allocates memory for the entire last_values structure, which _includes_
your three pointers. However, they aren't pointing _to_ anything, yet.

When you do:

lst_ptr->lst_t = malloc(sizeof(double));
lst_ptr->lst_vc = malloc(sizeof(double));
lst_ptr->lst_ic = malloc(sizeof(double));

These are allocating space for the _actual double values_, and assigning
the pointers to theses values to the various members of lst_ptr.

However, I think, given your goal, you are going about this entirely the
wrong way. I do not know why you would even need a structure of
pointers for this, as opposed to just a structure of doubles.
2) Where and how should I define my structure last values assuming
that I
have no ability to change the related *_h file. i.e. can I just
do it at
the start of the function I'm creating everything in of do I have
to do
> it at a higher level?

I have no idea what you are trying to do here. What function are you
trying to call? What "h" files are you trying to use? It looks like
some sort of generic callback-with-data interface. Anyway, it would at
least appear that you are way overusing pointers. Can you make it work
with just:

typedef struct {
double lst_t, lst_vc, lst_ic;
} last_values;

That seems to be a much easier plan. You can rid yourself of 3 malloc's
(and free's!) that way.

Jon
 
S

steve

I'm trying to create a structure of three pointers to doubles. For
which I have:

typedef struct {
double *lst_t, *lst_vc, *lst_ic;
} last_values;

I then need to allocate space for last_values as well as assign the
value of a pointer to the assigned space. Which I think I'm doing by
using:

last_values *lst_ptr = malloc(sizeof(*lst_ptr));

I then want to associate the pointer *lst_ptr to an existing void
pointer in another structure that is defined as:

typedef struct _UserInstDef UserInstDef;
struct _UserInstDef {
char *tag;
void current_mask;
void *seniorData;
};

I do this by using:

UserInstDef->seniorData = lst_ptr;

And then I finally allocate space for all of the pointers to doubles
as:

lst_ptr->lst_t = malloc(sizeof(double));
lst_ptr->lst_vc = malloc(sizeof(double));
lst_ptr->lst_ic = malloc(sizeof(double));

The goal behind all of this is to be allocating space for 3 double
values and their pointers and then link those values to an existing
pionter so I can "smuggle" the values out of a function where I've just
created them.


My questions are these:
1) Do I have to allocate space for the doubles lst_t, lst_vc, lst_ic
as well
as their pointers?
2) Where and how should I define my structure last values assuming
that I
have no ability to change the related *_h file. i.e. can I just
do it at
the start of the function I'm creating everything in of do I have
to do
it at a higher level?
3) Is there something wrong with the line:
last_values *lst_ptr = malloc(sizeof(*lst_ptr));
Am I missing something fundamental here?

I'm pretty new to C so any help is appreciated.

Thanks for your time,

Steve
 
R

Richard Bos

steve said:
I'm trying to create a structure of three pointers to doubles. For
which I have:

typedef struct {
double *lst_t, *lst_vc, *lst_ic;
} last_values;

I then need to allocate space for last_values as well as assign the
value of a pointer to the assigned space. Which I think I'm doing by
using:

last_values *lst_ptr = malloc(sizeof(*lst_ptr));

I then want to associate the pointer *lst_ptr to an existing void
pointer in another structure that is defined as:

typedef struct _UserInstDef UserInstDef;
struct _UserInstDef {
char *tag;
void current_mask;
void *seniorData;
};

I do this by using:

UserInstDef->seniorData = lst_ptr;

And then I finally allocate space for all of the pointers to doubles
as:

lst_ptr->lst_t = malloc(sizeof(double));
lst_ptr->lst_vc = malloc(sizeof(double));
lst_ptr->lst_ic = malloc(sizeof(double));

The goal behind all of this is to be allocating space for 3 double
values and their pointers and then link those values to an existing
pionter so I can "smuggle" the values out of a function where I've just
created them.


My questions are these:
1) Do I have to allocate space for the doubles lst_t, lst_vc, lst_ic
as well as their pointers?

Yes, or find some other way to point them at some valid address - for
example, by assigning the address of a "normal" double to them.
2) Where and how should I define my structure last values assuming
that I have no ability to change the related *_h file. i.e. can I just
do it at the start of the function I'm creating everything in of do I have
to do it at a higher level?

That depends mostly on the structure of the program you're writing.
3) Is there something wrong with the line:
last_values *lst_ptr = malloc(sizeof(*lst_ptr));
Am I missing something fundamental here?

As long as you have #include <stdlib.h>, nothing.

Richard
 
S

steve

For my second question there, is declaring the structure in the
procedure where I "attach" the structure to the seniorData pointer ok.
I seem to recall something to do with the structure losing scope when
the procedure is exited. If that is the case can I just define the
structure at the top of the *.c file?

Sorry for the level of the questions but it's been years since I've
used c and even then it was c++.

Thanks again for the help.
 
S

steve

Now that you mention it, using three doubles would work just fine. Not
sure how I came up with the idea for using the pointers.

So I would create the structure of three doubles and then make
seniorData point to the new structure. That does seem much easier.

As for the definition of the structure. The hearder file corresponding
to my c file is automatically generated by the software using my code
(long story). i.e. I'm writing file.c and file_h.c I can't change (I
think calling it the header file is the right term but I could be way
off). Basically what I'm asking is if I create the structure in a
function, say pre_analysis, and attach the structure to the one
variable that is passed to the function that I can mess around with
will the structure still be there for other functions to use the data
through userInst->seniorData->lst_* (* in the wildcard sense, not
pointer sense)?

Thanks again for the help
 
N

Netocrat

What you've written isn't syntactically valid since UserInstDef is a type,
not a variable. I'm assuming that you're using UserInstDef here to refer
to a variable of type UserInstDef *, in which case what you've written
makes sense. If your variable truly is of type UserInstDef, you'd need to
replace the '->' operator with '.' as in:

variableOfTypeUserInstDef.seniorData = lst_ptr;

You may have a valid reason to use pointers to doubles rather than plain
doubles, but if so you haven't explained it. Is there any reason why you
can't instead write:

typedef struct {
double lst_t, lst_vc, lst_ic;
} last_values;

And replace your references to lst_ptr->lst_t with &lst_ptr->lst_t;
similarly for lst_vc and lst_ic.
Yes, or find some other way to point them at some valid address - for
example, by assigning the address of a "normal" double to them.

If you use the code I gave above, then there is no need for any
allocations apart from:

last_values *lst_ptr = malloc(sizeof(*lst_ptr));

I don't see any point in only doing it at the start of the function in
which you're creating everything since then it will only have scope in
that function. You won't be able to use variables of that type anywhere
else. Surely you will need to use it after you have assigned it...
That depends mostly on the structure of the program you're writing.


As long as you have #include <stdlib.h>, nothing.

And remember to check whether malloc returned NULL.

Also to quote your reply post:
For my second question there, is declaring the structure in the procedure
where I "attach" the structure to the seniorData pointer ok. I seem to
recall something to do with the structure losing scope when the procedure
is exited. If that is the case can I just define the structure at the
top of the *.c file?

You need to declare the structure so that it is in scope any time you want
to access a variable of that type (or a pointer to that type). You are
correct - as I have already explained it does go out of scope when you
exit that function.

So it sounds OK to just define it at the top of the *.c file if that's the
only place you will actually use it.

In other words, any files where you use UserInstDef but don't access its
seniorData member as struct *last_values - and don't in any other way
use a variable of type struct last_values or struct *last_values - don't
require struct last_values to be in scope. This applies even if you have
previously assigned a variable of type struct *last_values to the
seniorData member - the assignment will remain valid even though you can
only access it as void * and not struct *last_values.
 
S

steve

I wasn't aware of the "->" vs "." difference, that's solved a few
errors right there.

As for the double vs. pointer purely an oversight due to lack of
experience. I think I orignally thought pointers would have a sort of
global scope. Then I realized that made no sense and never realized
that using the pointers instead of just doubles makes just about as
much sense.

Right now I've got the declaration of the struct at the top of the c
file and that's the only place it's used so my scope should now be
fine.

I haven't forgotten about the NULL checks, but thanks for the reminder.

All in all the code should pretty much be polished thanks to all your
help.

Cheers and thanks again,

Steve
 
C

CBFalconer

.... snip overly complex solution effort ...
The goal behind all of this is to be allocating space for 3 double
values and their pointers and then link those values to an existing
pionter so I can "smuggle" the values out of a function where I've
just created them.

See what this does for you:

/* just define a type and give it a name */
/* a struct label lives in a different namespace */
/* all the typedef does is avoid retyping struct elsewhere */
typedef struct smuggled {
double v1, v2, v3;
} smuggled;

smuggled smuggler(/* params as needed */)
{
smuggled localvalue;

/* gyrations */
localvalue.v1 = firstvalue;
localvalue.v2 = secondvalue;
localvalue.v3 = thirdvalue;
return localvalue;
}

void smuguser(....)
{
smuggled data;

....
data = smuggler(...);
fprintf("The product is %f\n", data.v1 * data.v2 * data.v3);
....
}

many would prefer to replace the word 'smuggled' with "struct
smuggled" everywhere except in the original typedef, which would
become a simple struct definition:

struct smuggled {
double v1, v2, v3;
};

No gyrations with malloc, pointers, etc. are needed. KISS.

BTW, don't regret having given your solution. We respect people
who make an effort. The above assumes that I understand your
objective properly.
 
R

Rajan

1) Do I have to allocate space for the doubles lst_t, lst_vc, lst_ic
as well
as their pointers?
I think you need not allocate memory for the structure here, you can
just create an instance by writing.
last_values l_val;
But you need to allocate memory for the doubles pointers for that
structure.
I find that you have not typecasted the doubles pointers while
allocating memory , this could give you warnings which can be
irritating.
As far as following is concerned, I feel that if you want to assign
this to void pointer you can do the following
Moreover UserInstDef is a structure name for which you have'nt created
an instance of this struct so you have to create UserInstDef
userInstance;
userInstance->seniorData = (void *)&l_val;

2) Where and how should I define my structure last values assuming
that I
have no ability to change the related *_h file. i.e. can I just
do it at
the start of the function I'm creating everything in of do I have

to do
it at a higher level?

Doing at a higher level is always safer because if you were to use that
struct instance in a function above the declaration of the structure
then you won't be able to compile it since the function above does'nt
know anything about this struct.


3) Is there something wrong with the line:
last_values *lst_ptr = malloc(sizeof(*lst_ptr));
Am I missing something fundamental here?

There is no reason why you should allocate in the first place. As I
have written at the top you can just create an instance last_values
l_val; which should suffice.
 
P

pete

Rajan said:
I find that you have not typecasted the doubles pointers while
allocating memory , this could give you warnings which can be
irritating.

No.
If lack of cast while allocating memory,
gives you warnings,
then your code has other problems that you need to know about.
 
R

Rajan

Pete,
As we know that malloc() returns a void* , it's always advisable to
typecast it, otherwise it gives warnings , following is the code and
then warnings after compilation.

int main()
{
last_values l_val;
UserInstDef userInstance;
l_val.lst_t = malloc(sizeof(double));
l_val.lst_vc = malloc(sizeof(double));
l_val.lst_ic = malloc(sizeof(double));
userInstance.seniorData = (void *)&l_val;
return 0;
}

s.c:18: warning: assignment makes pointer from integer without a cast
s.c:19: warning: assignment makes pointer from integer without a cast
s.c:20: warning: assignment makes pointer from integer without a cast

These lines which are displayed are exactly the ones wherein it has
been malloc'd.

C compilers are strict about typecasting and they will throw such
warnings.
If you don't see these warnings after compilation then probably you
need to do gcc s.c -Wall to see these warnings.
It's surprising that you don't get any warnings.
 
R

Richard Bos

[ I have no idea whom you're replying to. Do learn to post, okay?
Google's imbecility is not your excuse. ]
As we know that malloc() returns a void* , it's always advisable to
typecast it,

Precisely _because_ malloc() returns void *, does it not need, indeed
should it not get, a cast. void * was created purposely as a generic
object pointer, to avoid unnecessary casts. Otherwise, what would be the
use of a void *? We might as well use char *s.
otherwise it gives warnings ,

Not if you're compiling correct C, it doesn't.
int main()
{
last_values l_val;
UserInstDef userInstance;
l_val.lst_t = malloc(sizeof(double));

You invoke undefined behaviour here. Adding a cast will only mask the
problem, which is _not_ that you're assigning a void * somewhere.

The real problem is that you do not have a declaration for malloc() in
scope. This means that your compiler is forced to assume that it returns
an int, which is not correct; this means that trying to read that
non-existent int causes undefined behaviour: any result may follow.

The solution is not shutting up the valid warning from the compiler,
using a cast, but to get rid of the error by adding the declaration for
malloc(). The most expedient means for this is to #include <stdlib.h>

If that doesn't stop the warning _and_ get rid of the underlying
problem, you're not compiling C. Probably, you're using some bastard of
C and C++.

Richard
 
M

Martin Ambuhl

Rajan said:
Pete,
As we know that malloc() returns a void* ,
True...

it's always advisable to
typecast it,

False. We know no such thing. In fact, anyone who "knows" such a thing
probably "knows" all manner of other untrue things.
otherwise it gives warnings ,

No C compiler is required to issue a diagnostic. Of course C compilers
_may_ issue spurious warnings like
"Warning: You have used 'green' as a variable name. I don't like
that."
But you should recognize such warnings as bogus.
Most likely you are using a C++ compiler if you get such warnings. If
you use a C++ compiler, you should be writing in the programming
language C++ and posting to comp.lang.c++. If you want to write C and
post to comp.lang.c, then learn that your claim is false.
following is the code and
then warnings after compilation.

Your warnings,
s.c:18: warning: assignment makes pointer from integer without a cast
s.c:19: warning: assignment makes pointer from integer without a cast
s.c:20: warning: assignment makes pointer from integer without a cast

come from you error in #including <stdlib.h>. Because you write
incorrect code and don't know it, you misdiagnose your problem and then
claim to "know" things that are patently false.
C compilers are strict about typecasting and they will throw such
warnings.
If you don't see these warnings after compilation then probably you
need to do gcc s.c -Wall to see these warnings.

I have almost every possible warning enabled -- many more and including
all those from 'gcc -Wall' -- and never see such messages. Why? Because
I don't make your beginner's error.
It's surprising that you don't get any warnings.

It's surprising you pass off your ignorance for wisdom.
 
C

CBFalconer

Rajan said:
As we know that malloc() returns a void* , it's always advisable
to typecast it, otherwise it gives warnings , following is the
code and then warnings after compilation.

Extremely BAD advice. Others have explained why. DON'T CAST MALLOC.
 
F

Flash Gordon

Rajan said:
Pete,
As we know that malloc() returns a void* , it's always advisable to
typecast it, otherwise it gives warnings ,

In which case YOU are doing something wrong.
> following is the code and
then warnings after compilation.

int main()
{
last_values l_val;
UserInstDef userInstance;
l_val.lst_t = malloc(sizeof(double));
l_val.lst_vc = malloc(sizeof(double));
l_val.lst_ic = malloc(sizeof(double));
userInstance.seniorData = (void *)&l_val;
return 0;
}

s.c:18: warning: assignment makes pointer from integer without a cast
s.c:19: warning: assignment makes pointer from integer without a cast
s.c:20: warning: assignment makes pointer from integer without a cast

These lines which are displayed are exactly the ones wherein it has
been malloc'd.

C compilers are strict about typecasting and they will throw such
warnings.

Not with void* pointers they are not, and malloc returns void*. Try
reading the warnings you got. The bit about converting from INTEGER.
If you don't see these warnings after compilation then probably you
need to do gcc s.c -Wall to see these warnings.
It's surprising that you don't get any warnings.

No, Pete does not see the warnings because he has a prototype for malloc
in scope. This is conventionally done by including stdlib.h

Try compiling:

/* Beginning of source file */
#include <stdlib.h>
int main(void)
{
int *ptr = malloc(sizeof *ptr);
free(ptr);
return 0;
}
/* End of source code */

I also suggest gcc -ansi -pedantic -Wall s.c
 
P

pete

Rajan said:
Pete,
As we know that malloc() returns a void* , it's
always
Never.

advisable to typecast it,

ITYM cast. Typecasting is something that happens to thespians.
l_val.lst_ic = malloc(sizeof(double));
s.c:20: warning: assignment makes pointer from integer without a cast


You neglected to #include <stdlib.h>.

That's what the warning is telling you.

Consider:
warning: assignment makes pointer from integer without a cast

Integer? What integer? There's no integer there.
In C89 when you neglect to include the prototype
prior to a function call,
the compiler assumes that it returns type int.
 
R

Rajan

Well, thanks for the advice.Will follow that. I have always come across
application which are always been typecasted and probably yes they may
not have included <stdlib.h>
 
J

john_bode

Rajan said:
Well, thanks for the advice.Will follow that. I have always come across
application which are always been typecasted and probably yes they may
not have included <stdlib.h>

Before C89, the void* type didn't exist; malloc() and calloc() returned
char*, so a cast *was* necessary if you were assigning the result to a
different pointer type. Since C89, malloc() and calloc() return void*,
which does not require a cast[1]. What you saw was either old code, or
code written by an old C programmer.

1. Note that this is not the case in C++, but if you're writing C++,
you should be using new instead of malloc() anyway.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top