Pointers, question and fact confirmation please

H

halfmaddad

Hi Everyone !

Could you confirm that the facts I am operating under are correct and help with a question I do not know the answer to?

Pointers sure are tricky and I am not sure I fully understand all the details.

is this correct?:

I know that pointers need to match the types of the items they point to butpointers are also just addresses and those are the same size(on the same machine) so the space that any pointer occupies ought to be the same.

Is this correct:

Do pointers need to match their type so that the compiler knows to reserve enough space for the pointed-to-item?



here is a bit of pseudo code:

massive_struct foo ;

foo = init_massive() ;

is this correct:

foo is a pointer, likely the same size as integer and it's pointing to an address and there are enough bytes after this address to accommodate all thedata for a massive_struct instance. The call to init_massive populates thefirst address and the bytes following it with various members, ints, function pointers etc.

Question, assuming that massive_struct took up 20 bytes of space would thiswork?:

I have barely touched memory management but if 20 bytes of memory were allocated and a pointer pointed to it, could the call to init_massive correctlypopulate that area of memory?

This doesn't make any sense in C but I am trying to figure out ways to store complex C structs for C bindings. If language X could allocate space for massive_struct and give that space a name, I am wondering if calls from init_massive could populate the space set aside by another language. The instance of that struct would then have a non-C variable name

Thanks for reading-Patrick
 
B

Ben Bacarisse

Could you confirm that the facts I am operating under are correct and
help with a question I do not know the answer to?

Pointers sure are tricky and I am not sure I fully understand all the details.

is this correct?:

I know that pointers need to match the types of the items they point
to but pointers are also just addresses and those are the same size(on
the same machine) so the space that any pointer occupies ought to be
the same.

"Match" is the key here. You can use a void * to point at any object.
Also, you can use a char * to access the bytes of any object.
Is this correct:

Do pointers need to match their type so that the compiler knows to
reserve enough space for the pointed-to-item?

In general, pointers are entirely separate from the things they point
to. The compiler does not reserve space for the pointed-to things
(indeed there may be nothing pointed to):

void *vp = 0; // I point to nothing and my "pointed-to" type
// is distinct from every object type
here is a bit of pseudo code:

Code is better. The pseudo part often just confuses matters.
massive_struct foo ;

foo = init_massive() ;

is this correct:

foo is a pointer,

If you say so. It would have been better to show that and to name the
type in a way that suggests it is not a struct type but a pointer type.
likely the same size as integer

You probably mean int. C has lots of integer types, and one of them is
very likely the same size as a pointer, but int often isn't.
and it's pointing to an address and there are enough bytes after this
address to accommodate all the data for a massive_struct instance.

No, you've lost me. I think you should try a few examples in C rather
in pseudo code.
The
call to init_massive populates the first address and the bytes
following it with various members, ints, function pointers etc.

Question, assuming that massive_struct took up 20 bytes of space would
this work?:

I have barely touched memory management but if 20 bytes of memory were
allocated and a pointer pointed to it, could the call to init_massive
correctly populate that area of memory?

This doesn't make any sense in C but I am trying to figure out ways to
store complex C structs for C bindings. If language X could allocate
space for massive_struct and give that space a name, I am wondering if
calls from init_massive could populate the space set aside by another
language. The instance of that struct would then have a non-C variable
name

That's all too vague for me hazard a guess at an answer. If you are
not thinking simply in general terms (i.e. if you have a specific
problem interfacing language X to C, or C to language X) then please be
specific.
 
K

Keith Thompson

Could you confirm that the facts I am operating under are correct and
help with a question I do not know the answer to?

Pointers sure are tricky and I am not sure I fully understand all the
details.

is this correct?:

So far, yes. :cool:}
I know that pointers need to match the types of the items they point
to but pointers are also just addresses and those are the same size(on
the same machine) so the space that any pointer occupies ought to be
the same.

Pointers are not "just addresses" in the sense you mean. The are "just
addresses" in the sense that the C standard use the word "address" to
mean a value of pointer type -- which means that addresses, as C uses
the word, are typed.

Every pointer value is of some specific pointer type, which specifies
the type of the object it points to. void* is a special case, a generic
pointer type that can point to anything -- but you can't dereference a
void* without first converting it to some other pointer-to-object type.

For *most* C implementations, all pointer types happen have the same
size, but the C standard does not guarantee this, or even imply that it
should be the case. void* and char* are required to have the same size
and representation, but there are plausible reasons for char* to be
bigger than int* (if, say, an underlying machine address points to a
word, and extra information is needed to specify a byte within that
word).

And pointers to functions can be quite different from object pointers.

The language also makes some guarantees about the sizes of pointers to
structs and to unions.

In any case, there's generally no need to *assume* that all pointers are
the same size. If you need to know the size of a pointer, use "sizeof".
Is this correct:

Do pointers need to match their type so that the compiler knows to
reserve enough space for the pointed-to-item?

The compiler *doesn't* reserve space for the pointed-to item. You have
to do that yourself. If you allocate it dynamically, "sizeof" lets you
determine how much space to allocate. For example:

some_type *ptr;
ptr = malloc(sizeof(*ptr));
if (ptr == NULL) {
/* handle allocation failure */
}

Section 4 of the comp.lang.c FAQ, <http://www.c-faq.com/>, covers
pointers. Sections 5 and 6 are also relevant.

[snip]
 
A

Andrew Smallshaw

Do pointers need to match their type so that the compiler knows
to reserve enough space for the pointed-to-item?

Possibly, given a suitably generous parsing of this statement.
The compiler never needs to allocate space for the pointed-to type
based on the pointer - the space to allocate is determined by
reference to the pointed-to type itself or by sizeof depending on
the nature of the allocation. However, the compiler still needs
to know the size of the underlying type so that basic arithmetic
functions work. Consider a simple snippet:

example_t array[20];
example_t *pointer = &array[10];
pointer = pointer + 1;
/* Where does pointer point to? */

The answer in C is that pointer points to array[11]. If you use
an overly simple model of a pointer that would only be the case if
(sizeof(example_t) == 1).

If the size was two and the pointer was a simple byte address it
would be pointing at the second half of array[10] and the first
half of array[11]. Similarly, our example_t type could actually
be of size 28 or 49,286.

It becomes obvious that some scaling is needed somewhere along the
line to allow for the size of the underlying type. The pointer
types conatin that information.
 
M

Malcolm McLean

is this correct?:

I know that pointers need to match the types of the items they point to
but pointers are also just addresses and those are the same size(on the
same machine) so the space that any pointer occupies ought to be the same.
Pointers are addresses. They normally match the data items they point to,
but it's possible to defeat the system so that, for example a pointer to a
short actually points to space occupied by a double in memory. Pointers
are virtually always the same size regardless of type, because they are
just addresses, but that's not totally guaranteed. On a few systems char *s
have extra bits because the undelying hardware won;t allow 8-bit addressing.
Is this correct:

Do pointers need to match their type so that the compiler knows to reserve
enough space for the pointed-to-item?
No. Declaring a pointer just creates an address variable, set to a random
garbage value which may or may not be a valid memory address. When you
initalise a pointer, you set it either to null, or to point to some object
of the right type. The system won't reserve any space for you, the object
has to exist.
here is a bit of pseudo code:

massive_struct foo ;

foo = init_massive() ;


is this correct:



foo is a pointer, likely the same size as integer and it's pointing to an
address and there are enough bytes after this address to accommodate all
the data for a massive_struct instance. The call to init_massive populates
the first address and the bytes following it with various members, ints,
function pointers etc.
The question is badly posed. Since the snippet is pseudo_code and not C,
we can't say exactly what is intended.
In C it's normal to declare pointers, then initalise them with the return
from malloc(), then set the fields of the structure, particularly id the
struct is ver large. If a structure is small, it's also normal to create
one onthe stack, the npass its address to a subroutine to populate.
Question, assuming that massive_struct took up 20 bytes of space would
this work?:

I have barely touched memory management but if 20 bytes of memory were
allocated and a pointer pointed to it, could the call to init_massive
correctly populate that area of memory?
You need to get 20 bytes of space, and you need to ensure that it is
aligned strictly enough for the structure. The two normal ways of doing
this are
massive_struct *ptr =malloc( sizeof(massive_struct));
init_massive(ptr);

or
massive_struct instance;
init_massive(&instance);
This doesn't make any sense in C but I am trying to figure out ways to
store complex C structs for C bindings. If language X could allocate space
for massive_struct and give that space a name, I am wondering if calls
from init_massive could populate the space set aside by another language.
The instance of that struct would then have a non-C variable name
Generally this is how things are done. Make sure that the other language
is reserving 20 contiguous bytes in memory. You can then treat them as a
massive_struct, pass round a pointer to them, and write C functions to
do whatever you like.
However making sure that the C struct layout and the other language layout
is exactly the same can be a bit of a problem, depending on how C-like
the other language is.
 
H

halfmaddad

Thanks Ben

I usually bombard people with way too much info and a lot of the information is hard to read/non-sense but here goes...

So I really like Ada but there are some issues to overcome.

Ada has facilities for interfacing with other languages including C. However the process is a nightmare and Ada has horrible bindings. With Ada, pointers are called accesses. You can define accesses that point to classes or records and these records can mimic the layout of structs but the process isdeeply unpleasant and I can't even do this beyond trivial code. I was thinking that if I knew the size of a struct, I could create a pointer that points to a suitable amount of memory and instantiate the struct in this space.. I could refer to that struct from Ada code.

I don't really have real code to show, I am just trying to work through this in my head and I may be basing decisions are false facts.
 
H

halfmaddad

Sorry Ben, please look at my response a few paragraphs up. I thought it would appear at the bottom.

Hi Keith, hi Andrew, hi Malcolm

Thanks very much for helping me with this. Your answers were really great based on the what little you were given.

Here is some real code, although it's totally unrelated to what I am doing but will allow me to explain what I am thinking and where I am wrong a little clearer

lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);

This is from the Lua C API. I thought that lua_State was a complex struct that contained objects and function pointers and that the forward declaration on the first line would tell(or hit) the compiler to allocate enough space for it.

I thought that the luaL_newstate call propagated that memory space with the struct and that the LuaL_openlibs call added the optional libraries to it, possibly allocating more memory.

Is this sort of code perhaps a bad way to learn what is really going on as the library code may be calling a lot of code that does things implicitly ?

Thanks again
 
B

BartC

Sorry Ben, please look at my response a few paragraphs up. I thought it
would appear at the bottom.

Hi Keith, hi Andrew, hi Malcolm

Thanks very much for helping me with this. Your answers were really great
based on the what little you were given.

Here is some real code, although it's totally unrelated to what I am doing
but will allow me to explain what I am thinking and where I am wrong a
little clearer

lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);

This is from the Lua C API. I thought that lua_State was a complex struct
that contained objects and function pointers and that the forward
declaration on the first line would tell(or hit) the compiler to allocate
enough space for it.

No, the first line only declares a pointer (of 4 or 8 bytes usually). It
doesn't point to anything at this point.

The second line will initialise it: presumably luaL_newstate() creates or
allocates such a struct, and returns a pointer to it, which is stored in L.
Is this sort of code perhaps a bad way to learn what is really going on as
the library code may be calling a lot of code that does things implicitly
?

Look at something a bit simpler perhaps if you're not sure how pointers
work.
 
M

Malcolm McLean

Sorry Ben, please look at my response a few paragraphs up. I thought it
would appear at the bottom.

Hi Keith, hi Andrew, hi Malcolm

Thanks very much for helping me with this. Your answers were really great
based on the what little you were given.

Here is some real code, although it's totally unrelated to what I am doing
but will allow me to explain what I am thinking and where I am wrong a little
clearer

lua_State *L;

L = luaL_newstate();

luaL_openlibs(L);



This is from the Lua C API. I thought that lua_State was a complex struct
that contained objects and function pointers and that the forward declaration
on the first line would tell(or hit) the compiler to allocate enough space
for it.


I thought that the luaL_newstate call propagated that memory space with
the struct and that the LuaL_openlibs call added the optional libraries
to it, possibly allocating more memory.



Is this sort of code perhaps a bad way to learn what is really going on
as the library code may be calling a lot of code that does things implicitly ?
The Lua library will be complex, with maybe tens of thousands of lines of
code, but what's it's doing in fundamentally simple, and is this.

lua_State *L;

declares a point, currently intialised to a garbage memory address, that is
intended to point to a valid lua_State object, such as returned from the next
function.

L = luaL_newstate();

The function is probably written like this

lua_State *luaL_newstate(void)
{
lua_state *answer = malloc(szieof(lua_State));
if(!answer)
return NULL; /* fail on out of memory */
answer->field1 = someintiailvalueforfield1;

...

return answer;
}

Then we use it

void LuaL_openlibs(lua_State *L)
{
if(L->field1 == someintialvalueforfield1)
{
l_field1 = anewvalueforfield1;

...
}
else
{
/* field1 is not in initial state, so that means we
do different library-loading logic */
}
}


This is the standard C opaque pointer paradigm.
 
K

Keith Thompson

I usually bombard people with way too much info and a lot of the
information is hard to read/non-sense but here goes...

So I really like Ada but there are some issues to overcome.

Ada has facilities for interfacing with other languages including
C. However the process is a nightmare and Ada has horrible
bindings. With Ada, pointers are called accesses. You can define
accesses that point to classes or records and these records can mimic
the layout of structs but the process is deeply unpleasant and I can't
even do this beyond trivial code. I was thinking that if I knew the
size of a struct, I could create a pointer that points to a suitable
amount of memory and instantiate the struct in this space. I could
refer to that struct from Ada code.

I don't really have real code to show, I am just trying to work
through this in my head and I may be basing decisions are false facts.

Since it's Ada, not C, that defines Ada/C interfaces, you'll likely get
better answers about that in comp.lang.ada, but I'll try to answer
briefly.

If you have a C structure type that you want to access from Ada, there
are at least two possible approaches.

You can treat it as entirely opaque and do all the allocation from C,
making only pointers visible across the interface. This means the Ada
code will have no direct access to members of the structure; all such
access will be handled by calling C functions. If you need the size,
you can write a C function that computes "sizeof the_type" and call it
from Ada.

Or you can define an Ada record type whose layout exactly matches the C
structure type. If your C and Ada compilers are sufficiently closely
related (e.g., gcc and GNAT), this shouldn't be too difficult, but it
can still be a bit tricky.

One thing to watch out for: Ada's C interface assumes that structures
are always passed by reference, which is not the case. I think there's
a pragma (standard or non-standard) to override that and let you pass
C-compatible structures by value.
 
H

halfmaddad

Thanks once again Keith!

Hi Bart, thanks for your post.

"Look at something a bit simpler perhaps if you're not sure how pointers
work. "

While this is not a complaint against anyone in particular, this is one of my complaints about C books in general. I've read and read and read and then fallen on my face again and again with real world C code that quickly goes from pointer to some_int to luaL_newstate.

Thanks Malcolm. This is really helpful.

This has been a great day and a real turning point for me, I hope I can answer questions one day, I have received priceless help today
 
B

BartC

While this is not a complaint against anyone in particular, this is one of
my complaints about C books in general. I've read and read and read and
then fallen on my face again and again with real world C code that quickly
goes from pointer to some_int to luaL_newstate.

In the case of the lua_State* type (ie. 'pointer to lua_State'), this is not
something you need to understand to use that API. It's not even so relevant
that it is a pointer.

For example, you need to use a FILE* type to use C's file functions, but you
don't need to know anything about FILE*. Once you've got your FILE*
variable, as in f = fopen(...), then you just use this as needed, until you
get to fclose(f). Same with L = luaL_newstate().

So for that reason it's probably not a good way of trying to understand
pointers (do you ever actually need to dereference L, or directly access any
members using L->somemember? Probably not!)

I can't give any better examples however (I tend to keep away from other
people's C sources, ie. 'real world' programs, as I can never understand
them anyway).
 
J

James Kuyper

Hi Everyone !

Could you confirm that the facts I am operating under are correct and help with a question I do not know the answer to?

Pointers sure are tricky and I am not sure I fully understand all the details.

is this correct?:

I know that pointers need to match the types of the items they point to

Usually - but there are several exceptions to that rule, listed in
section 6.5p7.
... but pointers are also just addresses and those are the same size(on the same machine) so the space that any pointer occupies ought to be the same.

That is often the case, but the C standard imposes no such requirement,
and there have been (and still are) real systems where that is not true.
The single most common reason, as far as I know, is the existence of
systems where hardware addresses don't identify individual bytes, but
rather the start of a larger chunk of memory. Let the size of that chunk
be N bytes. Then for all types T such that _Alignof(T) >= N, a pointer
can simply be the address of one of those storage units. However, if
_Alignof(T) < N, a pointer must contain both the address of a storage
unit, and the equivalent of a byte offset within the storage unit. The
amount of memory needed to store that extra information may require
that, for instance, sizeof(char*) > sizeof(long double _Complex*).
Is this correct:

Do pointers need to match their type so that the compiler knows to reserve enough space for the pointed-to-item?

No, such reservations do not occur automatically, and it's your
responsibility for making sure that the amount of memory reserved is big
enough. There's many different ways of making it happen.
here is a bit of pseudo code:

massive_struct foo ;

foo = init_massive() ;

is this correct:

foo is a pointer, ...

That depends upon how massive_struct is defined. If it is a pointer
type, then it is very poorly named - that name implies that it's a
struct type.
... likely the same size as integer

There is no type named 'integer'. There is a type named 'int'. Pointers
are often the same size as 'int', but there's also many implementations
where they are not. Code that is intended to be portable should not
depend upon such assumptions.
and it's pointing to an address and there are enough bytes after this address to accommodate all the
data for a massive_struct instance. The call to init_massive populates
the first address and the bytes following it with various members, ints,
function pointers etc.

If 'massive_struct' is a pointer type, then that's a reasonable guess;
but you shouldn't bother guessing. Take a look at the documentation for
init_massive(), and find out. If no such documentation is available,
complain to the relevant authority - it should be.

If massive_struct is a struct type, as it's name implies, then 'foo'
itself is big enough to store the struct, and the call to init_massive()
creates a suitably initialized struct of the same type in a different
piece of memory. When that function returns, the object is copied from
that piece of memory, to foo. This is a sufficiently inefficient way of
doing things that it is generally done only for small structs, so it's
unlikely to apply to something named 'massive_struct'.
Question, assuming that massive_struct took up 20 bytes of space would this work?:

Given what you haven't told us about 'massive_struct', there's no way
for us to be sure. If it is struct type, 20 bytes would not count as
"massive". If it's a pointer type, on the other hand, 20 bytes is rather
larger than is needed by any machine I've ever used.
I have barely touched memory management but if 20 bytes of memory were allocated and a pointer pointed to it, could the call to init_massive correctly populate that area of memory?

In order to do that, init_massive() would have to know what that
location is. The most obvious way to do that would be for init_massive()
to take a pointer argument that points at the memory to be filled in.
You've given us no details about what init_massive() does, so it's
possible that it gets the address by some other method of passing the
pointer around (such as by using a global variable). The only way to
know is to look at documentation for init_massive().
 

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,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top