two dimensional arrays:

H

Hamish

I'm trying to use an C API which is for geometry calculations. The function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

polygons_num is the number of polygons in the calculation,
and polygons_vertex_num is the number of vertices on polygon i.

Can someone give me an example of how to fill this with valid data. Say the
data below:

typedef struct
{ coordpt pts[4]; //each polygon up to 4 vertices
} coordpts;

typedef struct
{ coordpts ptsa[3]; // up to 3 polygons
} polys;

polys * Data;

Data->ptsa[0].pts[0].x = 0;
Data->ptsa[0].pts[0].y = 0;
Data->ptsa[0].pts[1].x = 1;
Data->ptsa[0].pts[1].x = 0;
Data->ptsa[0].pts[2].x = 0;
Data->ptsa[0].pts[2].x = 1; // a triangle

Data->ptsa[1].pts[0].x = 0;
Data->ptsa[1].pts[0].y = 0;
Data->ptsa[1].pts[1].x = 1;
Data->ptsa[1].pts[1].x = 0;
Data->ptsa[1].pts[2].x = 1;
Data->ptsa[1].pts[2].x = 1;
Data->ptsa[1].pts[3].x = 0;
Data->ptsa[1].pts[3].x = 1; //a square

Data->ptsa[2].pts[0].x = 0;
Data->ptsa[2].pts[0].y = 0;
Data->ptsa[2].pts[1].x = 2;
Data->ptsa[2].pts[1].x = 0;
Data->ptsa[2].pts[2].x = 2;
Data->ptsa[2].pts[2].x = 2;
Data->ptsa[2].pts[3].x = 0;
Data->ptsa[2].pts[3].x = 2; //a bigger square

polygons_num = 3;
int polygons_vertex_num[3]; //vertices for up to 3 polygons
polygons_vertex_num[0] = 3;
polygons_vertex_num[1] = 4;
polygons_vertex_num[2] = 4;

Right, so I've got this data (actually this will be in a different format,
with std:vector but that's not important). I want to chuck it into my
coordpt **polygons

How do I do this easily?
 
B

Barry Schwarz

I'm trying to use an C API which is for geometry calculations. The function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]


The requirement is to use a pointer to pointer to type.
where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

polygons_num is the number of polygons in the calculation,
and polygons_vertex_num is the number of vertices on polygon i.

Can someone give me an example of how to fill this with valid data. Say the
data below:

typedef struct
{ coordpt pts[4]; //each polygon up to 4 vertices
} coordpts;


Here you have an array of type. In some cases, the array can be
treated as a pointer to type.
typedef struct
{ coordpts ptsa[3]; // up to 3 polygons
} polys;

Now you have built an array of array of type. This can NEVER be
treated as a pointer to pointer to type.
polys * Data;

At some point, Data must be initialized to point to something.
snip code that wants to initialize vertices
Right, so I've got this data (actually this will be in a different format,
with std:vector but that's not important). I want to chuck it into my

There is no stde:vector in C. First you need to decide which language
you will use.
coordpt **polygons

How do I do this easily?
If you want to build P polygons, each with V vertices, your need P
pointers, and each pointer must point to the first of V structs, for a
total of P*V structs.

If P is known at compile time, you can define an array of P pointers
to struct with
coordpt *polygons[P];

If not, you can allocate space for the P pointers during execution
after the value for P has been calculated or input with
coordpt **polygons;
polygons = malloc(P * sizeof *polygons);

If V is known at compile time, you can define an array of V structs
with
coordpt vertices_0[V];
and assign the address of this array (actually the address of the
first element of the array) to a pointer with
polygons[0] = vertices_0;
You would define P of these arrays and assign their addresses to the
pointers.

If V is not known until execution time, you can allocate space for the
vertices with
polygons[0] = malloc(V * sizeof *polygons[0]);
and you would do this P times, usually in a loop.

In any case, you would call the function with
func(polygons);


<<Remove the del for email>>
 
A

Axter

Hamish said:
I'm trying to use an C API which is for geometry calculations. The function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

polygons_num is the number of polygons in the calculation,
and polygons_vertex_num is the number of vertices on polygon i.

Can someone give me an example of how to fill this with valid data. Say the
data below:

typedef struct
{ coordpt pts[4]; //each polygon up to 4 vertices
} coordpts;

typedef struct
{ coordpts ptsa[3]; // up to 3 polygons
} polys;

polys * Data;

Data->ptsa[0].pts[0].x = 0;
Data->ptsa[0].pts[0].y = 0;
Data->ptsa[0].pts[1].x = 1;
Data->ptsa[0].pts[1].x = 0;
Data->ptsa[0].pts[2].x = 0;
Data->ptsa[0].pts[2].x = 1; // a triangle

Data->ptsa[1].pts[0].x = 0;
Data->ptsa[1].pts[0].y = 0;
Data->ptsa[1].pts[1].x = 1;
Data->ptsa[1].pts[1].x = 0;
Data->ptsa[1].pts[2].x = 1;
Data->ptsa[1].pts[2].x = 1;
Data->ptsa[1].pts[3].x = 0;
Data->ptsa[1].pts[3].x = 1; //a square

Data->ptsa[2].pts[0].x = 0;
Data->ptsa[2].pts[0].y = 0;
Data->ptsa[2].pts[1].x = 2;
Data->ptsa[2].pts[1].x = 0;
Data->ptsa[2].pts[2].x = 2;
Data->ptsa[2].pts[2].x = 2;
Data->ptsa[2].pts[3].x = 0;
Data->ptsa[2].pts[3].x = 2; //a bigger square

polygons_num = 3;
int polygons_vertex_num[3]; //vertices for up to 3 polygons
polygons_vertex_num[0] = 3;
polygons_vertex_num[1] = 4;
polygons_vertex_num[2] = 4;

Right, so I've got this data (actually this will be in a different format,
with std:vector but that's not important). I want to chuck it into my
coordpt **polygons

How do I do this easily?


Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);
 
B

Barry Schwarz

I'm trying to use an C API which is for geometry calculations. The function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;
snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);


Your macro translates as a call to a routine that returns a void** and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.

Furthermore, the routine allocates a block of void* and returns the
address of this block. Again, while this probably works on most
systems, there is no guarantee that sizeof(void*) is the same as
sizeof(coordpt*) or that the representation of an address in the two
pointer types is the same.

Since your two allocate functions use the same allocation logic, why
does one use void** and the other unsigned char**?

In the second function, you have a useless (and incorrect but
harmless) cast of the second argument to memcpy. Ignoring the const
in memcpy's prototype for a moment, memcpy expects a void*. The
function receives a void* as its argument. Why do you cast it to
unsigned char* just so the compiler will have to convert it back for
you?

Neither of your allocate functions checks the return from malloc for
success.


<<Remove the del for email>>
 
A

Axter

Barry said:
I'm trying to use an C API which is for geometry calculations. The function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;
snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);


Your macro translates as a call to a routine that returns a void** and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.


Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please give
specific reference to support your claim.
Furthermore, the routine allocates a block of void* and returns the
address of this block. Again, while this probably works on most
systems, there is no guarantee that sizeof(void*) is the same as
sizeof(coordpt*) or that the representation of an address in the two
pointer types is the same.

Again, please give specific reference to support this claim.
Since your two allocate functions use the same allocation logic, why
does one use void** and the other unsigned char**?

If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void pointer.
In the second function, you have a useless (and incorrect but
harmless) cast of the second argument to memcpy. Ignoring the const
in memcpy's prototype for a moment, memcpy expects a void*. The
function receives a void* as its argument. Why do you cast it to
unsigned char* just so the compiler will have to convert it back for
you?
Again, second function is not part of the discussion, and doesn't even
belong there.
Neither of your allocate functions checks the return from malloc for
success.

No. And that's intentional. This is example code, and added error
checking is left for the developer to add.
If you like to post a version with the added error check, please feel
free to do so, but the code I have posted in my site is not for that
purpose.
 
A

Axter

Emmanuel said:
Axter wrote on 30/04/05 :
Neither

#include <malloc.h>

nor

#include <memory.h>

are part of the C standard...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Thanks.
I never realized they were not part of the C standard.

I changed the code to include <stdlib.h> instead, which is part of the
standard.
 
B

Barry Schwarz

Barry said:
Hamish wrote:
I'm trying to use an C API which is for geometry calculations. The
function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;
snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);


Your macro translates as a call to a routine that returns a void** and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.


Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please give
specific reference to support your claim.


Paragraph 6.3.2.3-7 states it will work unless there is an alignment
issue. Since in your code the value is assigned by malloc which
guarantees that it is properly aligned for all types, alignment is not
an issue and I was wrong. It will work.
Again, please give specific reference to support this claim.

The only requirements for common size and representations are
contained in 6.2.5-27. There are four such requirements:

pointers to void and pointers to a character type
pointers to qualified and unqualified compatible types
pointers to any type of struct
pointers to any type of union

This paragraph concludes with "Pointers to other types need not have
the same representation or alignment requirements."
If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void pointer.

Nope. One is of type pointer to pointer to void and the other is
pointer to void (void** vs void*). These are not the same at all.
Again, second function is not part of the discussion, and doesn't even
belong there.


No. And that's intentional. This is example code, and added error
checking is left for the developer to add.
If you like to post a version with the added error check, please feel
free to do so, but the code I have posted in my site is not for that
purpose.



<<Remove the del for email>>
 
F

Flash Gordon

Axter said:
Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please give
specific reference to support your claim.

FAQ 4.9 says void ** is not a generic pointer to pointer.

In N869, 6.2.5:

| 27 A pointer to void shall have the same representation and alignment
| requirements as a pointer to a character type. Similarly, pointers
| to qualified or unqualified versions of compatible types shall have
| the same representation and alignment requirements.28) All pointers
| to structure types shall have the same representation and alignment
| requirements as each other. All pointers to union types shall have
| the same representation and alignment requirements as each other.
| Pointers to other types need not have the same representation or
| alignment requirements.

So no guarantee on void** provided there.

In 6.3.2.3 it specifies the various conversions allowed but again makes
no mention of void**. I won't quote the entire section since it is long.
Again, please give specific reference to support this claim.

Same references as above.

<snip>
 
C

CBFalconer

Axter said:
I never realized they were not part of the C standard.

I changed the code to include <stdlib.h> instead, which is part
of the standard.

For reference, from N869:

7.1.2 Standard headers

[#1] Each library function is declared, with a type that
includes a prototype, in a header,142) whose contents are
made available by the #include preprocessing directive. The
header declares a set of related functions, plus any
necessary types and additional macros needed to facilitate
their use. Declarations of types described in this clause
shall not include type qualifiers, unless explicitly stated
otherwise.

[#2] The standard headers are

<assert.h> <inttypes.h> <signal.h> <stdlib.h>
<complex.h> <iso646.h> <stdarg.h> <string.h>
<ctype.h> <limits.h> <stdbool.h> <tgmath.h>
<errno.h> <locale.h> <stddef.h> <time.h>
<fenv.h> <math.h> <stdint.h> <wchar.h>
<float.h> <setjmp.h> <stdio.h> <wctype.h>
 
A

Axter

Flash said:
FAQ 4.9 says void ** is not a generic pointer to pointer.

In N869, 6.2.5:

| 27 A pointer to void shall have the same representation and alignment
| requirements as a pointer to a character type. Similarly, pointers
| to qualified or unqualified versions of compatible types shall have
| the same representation and alignment requirements.28) All pointers
| to structure types shall have the same representation and alignment
| requirements as each other. All pointers to union types shall have
| the same representation and alignment requirements as each other.
| Pointers to other types need not have the same representation or
| alignment requirements.

So no guarantee on void** provided there.

The code is taking care of void** alignment by using sizeof(type), and
passing that to the first argument in the function.
The way the code is setup, it is garantee to work in any C compliant
compiler.
Neither you, nor Barry Schwarz have posted any thing that would show
otherwise.

The only way the code would fail, is if the compiler is not in full
compliance with the C standard.
 
A

Axter

Barry said:
Barry said:
Hamish wrote:
I'm trying to use an C API which is for geometry calculations. The
function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);

Your macro translates as a call to a routine that returns a void** and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.


Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please give
specific reference to support your claim.


Paragraph 6.3.2.3-7 states it will work unless there is an alignment
issue. Since in your code the value is assigned by malloc which
guarantees that it is properly aligned for all types, alignment is not
an issue and I was wrong. It will work.
Again, please give specific reference to support this claim.

The only requirements for common size and representations are
contained in 6.2.5-27. There are four such requirements:

pointers to void and pointers to a character type
pointers to qualified and unqualified compatible types
pointers to any type of struct
pointers to any type of union

This paragraph concludes with "Pointers to other types need not have
the same representation or alignment requirements."
If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void
pointer.

Nope. One is of type pointer to pointer to void and the other is
pointer to void (void** vs void*). These are not the same at all.


No duh. Of course, I didn't say they were the same.

Anyway, so we can conclude from this, that your first post is wrong,
and that this code is garantee to work as long as malloc does not fail.
 
P

pete

The only way the code would fail, is if the compiler is not in full
compliance with the C standard.

No.
The code fails if sizeof(void *) doesn't equal sizeof(coordpt *).

The return value of Allocate2DArray,
is a pointer to the first element of an array of (void *).

It can only be safely cast to a pointer to the first element
of an array of elemenents which have the same size as (void *).

If the element sizes are different,
then it's akin to doing something like this:

char array[5] = {0};
int *ptr = (int *)array;

and wrong.
 
B

Barry Schwarz

Barry said:
Barry Schwarz wrote:


Hamish wrote:
I'm trying to use an C API which is for geometry calculations. The
function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);

Your macro translates as a call to a routine that returns a void**
and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.

Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please give
specific reference to support your claim.


Paragraph 6.3.2.3-7 states it will work unless there is an alignment
issue. Since in your code the value is assigned by malloc which
guarantees that it is properly aligned for all types, alignment is not
an issue and I was wrong. It will work.
Furthermore, the routine allocates a block of void* and returns the
address of this block. Again, while this probably works on most
systems, there is no guarantee that sizeof(void*) is the same as
sizeof(coordpt*) or that the representation of an address in the two
pointer types is the same.

Again, please give specific reference to support this claim.

The only requirements for common size and representations are
contained in 6.2.5-27. There are four such requirements:

pointers to void and pointers to a character type
pointers to qualified and unqualified compatible types
pointers to any type of struct
pointers to any type of union

This paragraph concludes with "Pointers to other types need not have
the same representation or alignment requirements."
Since your two allocate functions use the same allocation logic, why
does one use void** and the other unsigned char**?

If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void
pointer.

Nope. One is of type pointer to pointer to void and the other is
pointer to void (void** vs void*). These are not the same at all.


No duh. Of course, I didn't say they were the same.

Anyway, so we can conclude from this, that your first post is wrong,
and that this code is garantee to work as long as malloc does not fail.


Not at all. We can conclude that your code WILL FAIL whenever
sizeof(void*) is different from sizeof(coordpt*) or whenever they have
different representations of the value.


<<Remove the del for email>>
 
A

Axter

Barry said:
Barry said:
Barry Schwarz wrote:


Hamish wrote:
I'm trying to use an C API which is for geometry
calculations.
The
function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);

Your macro translates as a call to a routine that returns a void**
and
then casts that value to the desired type. While this probably works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.

Could you please explain that with more details.
Why do you think there's no garantee that it will work, and
please
give
specific reference to support your claim.

Paragraph 6.3.2.3-7 states it will work unless there is an alignment
issue. Since in your code the value is assigned by malloc which
guarantees that it is properly aligned for all types, alignment is not
an issue and I was wrong. It will work.


Furthermore, the routine allocates a block of void* and returns the
address of this block. Again, while this probably works on most
systems, there is no guarantee that sizeof(void*) is the same as
sizeof(coordpt*) or that the representation of an address in
the
two
pointer types is the same.

Again, please give specific reference to support this claim.

The only requirements for common size and representations are
contained in 6.2.5-27. There are four such requirements:

pointers to void and pointers to a character type
pointers to qualified and unqualified compatible types
pointers to any type of struct
pointers to any type of union

This paragraph concludes with "Pointers to other types need not have
the same representation or alignment requirements."



Since your two allocate functions use the same allocation
logic,
why
does one use void** and the other unsigned char**?

If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void pointer.

Nope. One is of type pointer to pointer to void and the other is
pointer to void (void** vs void*). These are not the same at all.

No duh. Of course, I didn't say they were the same.

Anyway, so we can conclude from this, that your first post is wrong,
and that this code is garantee to work as long as malloc does not
fail.

Not at all. We can conclude that your code WILL FAIL whenever
sizeof(void*) is different from sizeof(coordpt*) or whenever they have
different representations of the value.


You still have not shown what part of the standard supports this claim.
 
A

Axter

pete said:
The only way the code would fail, is if the compiler is not in full
compliance with the C standard.

No.
The code fails if sizeof(void *) doesn't equal sizeof(coordpt *).

The return value of Allocate2DArray,
is a pointer to the first element of an array of (void *).

It can only be safely cast to a pointer to the first element
of an array of elemenents which have the same size as (void *).

If the element sizes are different,
then it's akin to doing something like this:

char array[5] = {0};
int *ptr = (int *)array;

and wrong.

That's what I figure you were thinking.
And I can assure you that you're completely wrong.
You're comparing an array of pointers to an array of objects.
They're completely different things.
That's like saying that sizeof(foo *) is equal to sizeof(foo)
 
P

pete

Axter said:
Axter said:
coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);
| Pointers to other types need not have the
| same representation or alignment requirements.
The only way the code would fail,
is if the compiler is not in full
compliance with the C standard.

No.
The code fails if sizeof(void *) doesn't equal sizeof(coordpt *).

The return value of Allocate2DArray,
is a pointer to the first element of an array of (void *).

It can only be safely cast to a pointer to the first element
of an array of elemenents which have the same size as (void *).

If the element sizes are different,
then it's akin to doing something like this:

char array[5] = {0};
int *ptr = (int *)array;

and wrong.
That's what I figure you were thinking.
Good.

And I can assure you that you're completely wrong.

You can try.
You're comparing an array of pointers to an array of objects.

You're casting a pointer to one type of pointer,
to a pointer to another type of pointer.
They're completely different things.

No.
They are completely different types of objects.
Pointer types are object types and
your array of pointers is an array of objects.
That's like saying that sizeof(foo *) is equal to sizeof(foo)

I don't see how.
 
F

Flash Gordon

pete said:
Axter wrote:


You're casting a pointer to one type of pointer,
to a pointer to another type of pointer.

I agree with pete.

Perhaps one of the regulars has used a system where a t least one
pointer type has a different representation to a pointer to void? I know
some people round here have used strange systems :)
 
?

=?iso-8859-1?q?Dag-Erling_Sm=F8rgrav?=

Flash Gordon said:
Perhaps one of the regulars has used a system where a t least one
pointer type has a different representation to a pointer to void? I
know some people round here have used strange systems :)

I believe void * is required to be assignment compatible with any
other kind of pointer except a function pointer.

I believe the point Pete was making, however, is that you are not
permitted to access an object through a pointer to anything but the
object's type, a compatible type, or char. Pointers to void are not
used to access anything; they are always cast or assigned to some
other pointer type before use.

DES
 
B

Barry Schwarz

Barry said:
Barry Schwarz wrote:

Barry Schwarz wrote:


Hamish wrote:
I'm trying to use an C API which is for geometry calculations.
The
function
requires an argument for an array of polygons:

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num-1]

where coordpt is:

typedef struct
{ double x;
double y;
} coordpt;

snip

Check out the following code for building a 2 dimensional array:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

Using above code, you can create a 2 dimensional array via
following
method:
int x = 4;
int y = 6;

coordpt **My_coordpt = ALLOCATE2DARRAY(coordpt, x, y);

Your macro translates as a call to a routine that returns a void**
and
then casts that value to the desired type. While this probably
works
on most systems, there is no guarantee that a void** is in any way
compatible with coordpt** or that the conversion via the cast will
produce a meaningful value.

Could you please explain that with more details.
Why do you think there's no garantee that it will work, and please
give
specific reference to support your claim.

Paragraph 6.3.2.3-7 states it will work unless there is an alignment
issue. Since in your code the value is assigned by malloc which
guarantees that it is properly aligned for all types, alignment is
not
an issue and I was wrong. It will work.


Furthermore, the routine allocates a block of void* and returns
the
address of this block. Again, while this probably works on most
systems, there is no guarantee that sizeof(void*) is the same as
sizeof(coordpt*) or that the representation of an address in the
two
pointer types is the same.

Again, please give specific reference to support this claim.

The only requirements for common size and representations are
contained in 6.2.5-27. There are four such requirements:

pointers to void and pointers to a character type
pointers to qualified and unqualified compatible types
pointers to any type of struct
pointers to any type of union

This paragraph concludes with "Pointers to other types need not have
the same representation or alignment requirements."



Since your two allocate functions use the same allocation logic,
why
does one use void** and the other unsigned char**?

If you're referring to the code in the Allocate2DArrayWithValues
function, that is not part of the code I posted above, and it's not
really relevent the the poster's question.
It's a left over function, that didn't get removed.
The Allocate2DArray function is the function that creates the array,
and if you notice, both allocation pointers are of type void
pointer.

Nope. One is of type pointer to pointer to void and the other is
pointer to void (void** vs void*). These are not the same at all.


No duh. Of course, I didn't say they were the same.

Anyway, so we can conclude from this, that your first post is wrong,
and that this code is garantee to work as long as malloc does not
fail.

Not at all. We can conclude that your code WILL FAIL whenever
sizeof(void*) is different from sizeof(coordpt*) or whenever they have
different representations of the value.


You still have not shown what part of the standard supports this claim.


Go back and read 6.2.5-27 which I quoted for you. What more do you
need?


<<Remove the 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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top