is possible to build some pointer array?

Y

yezi

Hi, all:

I want to record some memory pointer returned from malloc, is possible
the code like below?

int memo_index[10];
int i,j;
char *tmp;

for (i=0;i<10;i++){
tmp = malloc(10);
memo_index = tmp;
}

what I want to realize is "use the memo_index [10] to record each
usable memory pointer, then I just use
memo_index to refer to each stuff installed in the allocated memory
/

Is it possible or some else way?

Thanks for any comments.

bin
 
R

rupesh_533

yezi said:
I want to record some memory pointer returned from malloc, is possible
the code like below?

int memo_index[10];

you want to record the address of a variable in memo_index so declare
it as a pointer.
int *memo_index[10].
int i,j;
char *tmp;

for (i=0;i<10;i++){
tmp = malloc(10);
memo_index = tmp;
}


malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.
 
K

Keith Thompson

malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


No, no, no.

malloc() returns a result of type void*, which will be implicitly
converted to any pointer-to-object type. Casting the result is
unnecessary, and can mask certain errors such as forgetting to
"#include <stdlib.h>" or using a C++ compiler.
 
S

slebetman

yezi said:
I want to record some memory pointer returned from malloc, is possible
the code like below?

int memo_index[10];

you want to record the address of a variable in memo_index so declare
it as a pointer.
int *memo_index[10].
int i,j;
char *tmp;

for (i=0;i<10;i++){
tmp = malloc(10);
memo_index = tmp;
}


malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


since tmp is a char, it should really be:

char *memo_index[10];

That is, an array of 10 char pointers. Although pointers are all the
same size, don't point to different typed data from different typed
pointers unless you really need to.
 
J

Jack Klein

yezi said:
I want to record some memory pointer returned from malloc, is possible
the code like below?

int memo_index[10];

you want to record the address of a variable in memo_index so declare
it as a pointer.
int *memo_index[10].
int i,j;
char *tmp;

for (i=0;i<10;i++){
tmp = malloc(10);
memo_index = tmp;
}


malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


since tmp is a char, it should really be:

char *memo_index[10];

That is, an array of 10 char pointers. Although pointers are all the
same size, don't point to different typed data from different typed
pointers unless you really need to.


There is no guarantee or requirement at all in C that all pointers are
the same size. The only guarantees are:

1. Pointer to void and pointer to any of the character types have the
same size and representation. These pointers can store the full
representation of a pointer to any other object type.

2. All pointers to structures and unions have the same size
representation.

3. All pointers to functions, regardless of the return type or
argument list, have the same size.
 
K

Keith Thompson

(e-mail address removed) wrote: [...]
malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


(I've already commented on this.)
since tmp is a char, it should really be:

char *memo_index[10];

That is, an array of 10 char pointers. Although pointers are all the
same size, don't point to different typed data from different typed
pointers unless you really need to.

You can't assume that all pointers are the same size; there are
systems on which they aren't.

If you want a generic pointer, use void*. (char* is guaranteed to
have the same representation and alignment requirements, but that's
for historical reasons.)
 
S

slebetman

Jack said:
There is no guarantee or requirement at all in C that all pointers are
the same size. The only guarantees are:

1. Pointer to void and pointer to any of the character types have the
same size and representation. These pointers can store the full
representation of a pointer to any other object type.

2. All pointers to structures and unions have the same size
representation.

3. All pointers to functions, regardless of the return type or
argument list, have the same size.

Hmm, a lot of code I've seen make the assumption that 1==2. Especially
TCP/IP libraries in Linux, Windows, BSD etc. that casts a char* into
structs to extract data from a packet.

If 1!=2, then you're saying that a void pointer should not ever point
to a struct. But this is how polymorphism is usually emulated in C.
Why, even malloc( ) returns a void pointer which can be used to point
to an area of memory to store a struct.

Besides, aren't pointers just addresses into memory? Why would a CPU
differentiate between structured and unstructured bytes? I can
understand the difference of function pointers since it points to an
area of executing code, not data memory, and in some systems these are
different address spaces.
 
R

rupesh_533

Keith said:
malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


No, no, no.

malloc() returns a result of type void*, which will be implicitly
converted to any pointer-to-object type. Casting the result is
unnecessary, and can mask certain errors such as forgetting to
"#include <stdlib.h>" or using a C++ compiler.

Then how we should assign the memo_index .
Is it like
memo_index=malloc(10);
then i am getting this warning
warning: assignment makes pointer from integer without a cast
 
K

Keith Thompson

Keith said:
malloc will return a void pointer so type cast it and assign it to
memo_index.
for (i=0;i<10;i++)
memo_index=(int *)malloc(10);
type casting depends on the way you want to use pointer.


No, no, no.

malloc() returns a result of type void*, which will be implicitly
converted to any pointer-to-object type. Casting the result is
unnecessary, and can mask certain errors such as forgetting to
"#include <stdlib.h>" or using a C++ compiler.

Then how we should assign the memo_index .
Is it like
memo_index=malloc(10);
then i am getting this warning
warning: assignment makes pointer from integer without a cast


See above. You need to add
#include <stdlib.h>
so the compiler can see the declaration of malloc(). Without that the
compiler assumes (incorrectly) that malloc() returns an int.

Using a cast tells the compiler "Trust me, I know what I'm doing". If
you don't actually know what you're doing, the compiler will get its
revenge.
 
R

Richard Bos

Keith said:
malloc() returns a result of type void*, which will be implicitly
converted to any pointer-to-object type. Casting the result is
unnecessary, and can mask certain errors such as forgetting to
"#include <stdlib.h>" or using a C++ compiler.
Then how we should assign the memo_index .
Is it like
memo_index=malloc(10);
then i am getting this warning
warning: assignment makes pointer from integer without a cast


Then either you have not #included <stdlib.h>, or you are not
programming in C but in an inferior clone.

Richard
 
S

Simon Biber

Keith said:
malloc() returns a result of type void*, which will be implicitly
converted to any pointer-to-object type. Casting the result is
unnecessary, and can mask certain errors such as forgetting to
"#include <stdlib.h>" or using a C++ compiler.

Then how we should assign the memo_index .
Is it like
memo_index=malloc(10);


You should multiply 10 by the size of an element of the array.

memo_index = malloc(10 * sizeof *memo_index);

An equivalent way of writing that is:

memo_index = malloc(10 * sizeof (int));

But the first way is better, because it will continue to work if you
change the type of memo_index. There is a simple pattern: whatever you
are assigning to, add 'sizeof *' to the left of it.
then i am getting this warning
warning: assignment makes pointer from integer without a cast

You must have forgotten to write the line
#include <stdlib.h>
at the top of your program.
 
R

Richard Bos

And

4. All pointers to a qualified type are the same size and representation
as the base type, and v.v.

5. Where it says "size and representation" in points 1-4, add alignment.
Hmm, a lot of code I've seen make the assumption that 1==2. Especially
TCP/IP libraries in Linux, Windows, BSD etc. that casts a char* into
structs to extract data from a packet.

If 1!=2, then you're saying that a void pointer should not ever point
to a struct.

No. A void pointer is guaranteed to be able to contain any other kind of
object pointer. The difference goes the other way 'round: a pointer to a
struct (or, for that matter, to any other type except char) may be
smaller, or require stricter alignment, than a void *. This means that
any object pointer value can be put in a void *; but a void * value can
not necessarily be assigned to any other object pointer. (One exception:
if I assign a <type> pointer value to a void *, I can always assign
_that_ void * value to any said:
Besides, aren't pointers just addresses into memory? Why would a CPU
differentiate between structured and unstructured bytes?

Because it can be used to speed up the code? Because certain types have
alignment requirements? Because your hardware address size addresses
36-bit words only and you want your bytes to be 9 bits?

Richard
 
S

Simon Biber

Hmm, a lot of code I've seen make the assumption that 1==2. Especially
TCP/IP libraries in Linux, Windows, BSD etc. that casts a char* into
structs to extract data from a packet.

It's not clever to use a struct type to extract data from memory,
because that struct may have different padding bytes inserted on
different C implementations (whether on the same platform or on
different platforms).
If 1!=2, then you're saying that a void pointer should not ever point
to a struct. But this is how polymorphism is usually emulated in C.
Why, even malloc( ) returns a void pointer which can be used to point
to an area of memory to store a struct.

Doing so involves a conversion from one pointer type to another. On any
system where different pointers have different representations, they
must be converted between formats when the conversion is done. This is
part of the syntax of C, it's just that most people would consider
pointer conversion as a no-op, since it is a no-op on most platforms.
Besides, aren't pointers just addresses into memory? Why would a CPU
differentiate between structured and unstructured bytes? I can
understand the difference of function pointers since it points to an
area of executing code, not data memory, and in some systems these are
different address spaces.

Some CPUs have native pointer types that address in words of more than
one byte. On such systems, it makes sense to use those native pointer
types when dealing with data types that are a multiple of the native
word size. Then, only void and char types must use an extended pointer
format, where one part is the address of the word, and the other part is
the offset within the word.
 
S

Simon Biber

Keith said:
You can't assume that all pointers are the same size; there are
systems on which they aren't.

If you want a generic pointer, use void*. (char* is guaranteed to
have the same representation and alignment requirements, but that's
for historical reasons.)

If char* and void* have the same representation and alignment
requirements, does that mean they are interchangeable as
a) arguments in a variable-length argument list?
b) arguments in an unprototyped function?
c) arguments in a function called with the incorrect prototype?
d) return values of a function called with the wrong declaration?

A simple example of a) is: printf("%p\n", "hello");

Is that guaranteed to be safe?

One reason that any of the above may not be safe is if char* and void*
are customarily passed in different registers on some system.
 
S

slebetman

Simon said:
It's not clever to use a struct type to extract data from memory,
because that struct may have different padding bytes inserted on
different C implementations (whether on the same platform or on
different platforms).

Yeah, but this is not only common, but standard practice when dealing
with networking code. Years ago I used to write code for communication
protocols and I used to extract data from packets byte-by-byte in for
loops. It's only 2 or 3 years ago that I started writing TCP/IP code
(libpcap etc..) that I noticed that people are using structs to extract
data form packets. Since it is so wide spread I didn't especially think
of it as 'clever' but just 'standard'.

Some CPUs have native pointer types that address in words of more than
one byte. On such systems, it makes sense to use those native pointer
types when dealing with data types that are a multiple of the native
word size. Then, only void and char types must use an extended pointer
format, where one part is the address of the word, and the other part is
the offset within the word.

Ah, I understand. Like ARM7 for instance which can only point to 32bit
alinged memory. So the compiler needs to generate code to handle
offsets in case of 8 and 16 bit data and the pointer format needs to
store this information somewhere.
 
S

slebetman

Richard said:
This means that any object pointer value can be put in a void *; but a void *
value can not necessarily be assigned to any other object pointer.
(One exception: if I assign a <type> pointer value to a void *, I can always assign
_that_ void * value to any <type> pointer.)

But I don't understand how malloc can be made to work with these rules.
Doesn't malloc just return a void pointer which in normal use you
assign to a variable you want. Isn't the following *normal* code?

struct mystruct *myptr;
myptr = malloc(sizeof(myptr));

Or is what Simon Biber said true, that is, the C runtime does some
pointer conversion in the background in this case. If so what's the
difference with:

struct mystruct *myptr;
void *tmp;
tmp = malloc(sizeof(myptr));
myptr = tmp;

I don't see how malloc can be useful if you can't assign a void pointer
to a struct pointer.
 
T

Tim Rentsch

And

4. All pointers to a qualified type are the same size and representation
as the base type, and v.v.

5. Where it says "size and representation" in points 1-4, add alignment.

And

6. Pointers to compatible types have the same representation etc
as each other.

Except

2'. Pointers to structures have the same representation etc as
each other; pointers to unions have the same representation etc
as each other; but pointers to structures and pointers to unions
might or might not have the same representation etc as each other.
 
T

Tim Rentsch

Simon Biber said:
If char* and void* have the same representation and alignment
requirements, does that mean they are interchangeable as
a) arguments in a variable-length argument list?
b) arguments in an unprototyped function?
c) arguments in a function called with the incorrect prototype?
d) return values of a function called with the wrong declaration?

A simple example of a) is: printf("%p\n", "hello");

Is that guaranteed to be safe?

The short answers are:

a) Yes
b) Yes if the function _definition_ has no prototype; No if it does
(with the call site having no prototype in either case)
c) No
d) No

One reason that any of the above may not be safe is if char* and void*
are customarily passed in different registers on some system.

In practical terms I expect all would work on at least the
vast majority of platforms. My answers however were based on
what the Standard says about the topic.
 
S

Simon Biber

But I don't understand how malloc can be made to work with these rules.
Doesn't malloc just return a void pointer which in normal use you
assign to a variable you want. Isn't the following *normal* code?

struct mystruct *myptr;
myptr = malloc(sizeof(myptr));

Yes it is normal code, apart from the wrong size as pete explained.

The conversion is implicit in the assignment from a "pointer to void" to
a "pointer to struct mystruct". The conversion is still performed,
behind the scenes. If the void* had some extra data to represent the
offset within a word, it will be stripped off when the pointer is converted.

Since malloc must return a pointer that is correctly aligned for any
data type, any offset part must logically be zero in any void* that is
returned from malloc.
Or is what Simon Biber said true, that is, the C runtime does some
pointer conversion in the background in this case. If so what's the
difference with:

struct mystruct *myptr;
void *tmp;
tmp = malloc(sizeof(myptr));
myptr = tmp;

There is no difference! In the line above, exactly the same conversion
is performed as in the previous block of code.
I don't see how malloc can be useful if you can't assign a void pointer
to a struct pointer.

I think you misunderstood somewhere. Nobody ever said you can't assign a
void pointer to a struct pointer. It's just that the two pointers may
have a different representation. When you do the assignment, the
pointers will automatically be converted as necessary.

Essentially, you don't need to worry about this unless you start doing
something dodgy, such as accessing a pointer *value* through an
expression of the wrong type.

For example,

/* Define foo as pointer to char, initialise with NULL */
char *foo = NULL;

/* Define bar as int, initialise with 42 */
int bar = 42;

/* Assign pointer to string "hello" to bar */
foo = "hello"; /* No problem */

/* Now define quux as pointer to pointer to int, and
initialise with a suitably converted pointer to foo. */

int **quux = (int **) &foo; /* Dodgy */

/* Find whatever quux points at, and assign it a pointer to bar */

*quux = &bar; /* Undefined Behaviour, but will succeed in
changing foo's value on most systems. */

Here, even accessing *quux was undefined behaviour, since it was
attempting to access a value of type (char *) through an expression of
type (int *).
 

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

No members online now.

Forum statistics

Threads
474,171
Messages
2,570,935
Members
47,472
Latest member
KarissaBor

Latest Threads

Top