473,326 Members | 2,126 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

two dimensional arrays:

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[i]-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[i] 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?
Nov 14 '05 #1
29 1943
On Sat, 30 Apr 2005 00:18:08 +1200, "Hamish" <h.****@xtra.co.nz>
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[i]-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[i] 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>>
Nov 14 '05 #2

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[i]-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[i] 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);

Nov 14 '05 #3
On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> wrote:

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

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num[i]-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>>
Nov 14 '05 #4
Axter wrote on 30/04/05 :
http://code.axter.com/allocate2darray.c

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++

Nov 14 '05 #5
Barry Schwarz wrote:
On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> wrote:

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

coordpt **polygons
//[0..i..polygons_num-1][0..polygons_vertex_num[i]-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.

Nov 14 '05 #6
Emmanuel Delahaye wrote:
Axter wrote on 30/04/05 :
http://code.axter.com/allocate2darray.c

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.

Nov 14 '05 #7
On 30 Apr 2005 18:15:14 -0700, "Axter" <te**@axter.com> wrote:
Barry Schwarz wrote:
On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> 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[i]-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.
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.


<<Remove the del for email>>
Nov 14 '05 #8
Axter wrote:
Barry Schwarz wrote:
On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> wrote:
Hamish wrote:
<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.


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


Same references as above.

<snip>
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #9
Axter wrote:
>>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.

--
pete
Nov 14 '05 #10
On 1 May 2005 04:55:32 -0700, "Axter" <te**@axter.com> wrote:
Barry Schwarz wrote:
On 30 Apr 2005 18:15:14 -0700, "Axter" <te**@axter.com> wrote:
>Barry Schwarz wrote:
>> On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> 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[i]-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 viafollowing >> >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 probablyworks >> 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 pleasegive >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 returnsthe >> 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 thetwo >> 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>>
Nov 14 '05 #11

Barry Schwarz wrote:
On 1 May 2005 04:55:32 -0700, "Axter" <te**@axter.com> wrote:
Barry Schwarz wrote:
On 30 Apr 2005 18:15:14 -0700, "Axter" <te**@axter.com> wrote:

>Barry Schwarz wrote:
>> On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> 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[i]-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 viafollowing
>> >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 pleasegive
>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 thetwo
>> 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.

Nov 14 '05 #12
pete wrote:
Axter wrote:
>>>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.

--
pete


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)

Nov 14 '05 #13
Axter wrote:

pete wrote:
Axter wrote:
> >>>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.

--
pete
Nov 14 '05 #14
pete wrote:
Axter wrote:


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


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 :-)
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #15
Flash Gordon <sp**@flash-gordon.me.uk> writes:
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
--
Dag-Erling Smørgrav - de*@des.no
Nov 14 '05 #16
On 1 May 2005 08:56:19 -0700, "Axter" <te**@axter.com> wrote:

Barry Schwarz wrote:
On 1 May 2005 04:55:32 -0700, "Axter" <te**@axter.com> wrote:
>Barry Schwarz wrote:
>> On 30 Apr 2005 18:15:14 -0700, "Axter" <te**@axter.com> wrote:
>>
>> >Barry Schwarz wrote:
>> >> On 30 Apr 2005 04:02:54 -0700, "Axter" <te**@axter.com> wrote:
>> >>
>> >> >
>> >> >Hamish wrote:
>> >> >> I'm trying to use an C API which is for geometrycalculations. >The
>> >> >function
>> >> >> requires an argument for an array of polygons:
>> >> >>
>> >> >> coordpt **polygons
>> >> >> //[0..i..polygons_num-1][0..polygons_vertex_num[i]-1]
>> >> >>
>> >> >> where coordpt is:
>> >> >>
>> >> >> typedef struct
>> >> >> { double x;
>> >> >> double y;
>> >> >> } coordpt;
>> >> >>
>> >> snip
>> >> >
>> >> >Check out the following code for building a 2 dimensionalarray: >> >> >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 avoid** >> >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 anyway >> >> compatible with coordpt** or that the conversion via the castwill >> >> produce a meaningful value.
>> >
>> >Could you please explain that with more details.
>> >Why do you think there's no garantee that it will work, andplease >give
>> >specific reference to support your claim.
>>
>> Paragraph 6.3.2.3-7 states it will work unless there is analignment >> 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 onmost >> >> systems, there is no guarantee that sizeof(void*) is the sameas >> >> sizeof(coordpt*) or that the representation of an address inthe >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 nothave >> the same representation or alignment requirements."
>>
>> >
>> >>
>> >> Since your two allocate functions use the same allocationlogic, >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'snot >> >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 thearray, >> >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>>
Nov 14 '05 #17
Dag-Erling Smørgrav wrote:
Flash Gordon <sp**@flash-gordon.me.uk> writes:
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.


Indeed.
I believe the point Pete was making,
I believe that Pete and I are in complete agreement.
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.
There are several cases where the standard allows you to assign a
pointer to another pointer type (some where a cast is required) and you
are guaranteed to get what you would expect. However, those cases don't
guarantee you can read that pointer (through another pointer) as a
pointer to a different type. Specifically, void* and char* are
guaranteed to have the same representation, but pointers to structs are
not guaranteed to have the same representation as pointers to void.
Pointers to void are not
used to access anything; they are always cast or assigned to some
other pointer type before use.


Yes, but irrelevant to what we were discussing.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #18

Dag-Erling Smørgrav wrote:
Flash Gordon <sp**@flash-gordon.me.uk> writes:
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.


I don't think that's the point he was trying to make, because it would
not apply to the code I posted.
The code I posted has it cast to the target pointer via the macro.
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

If I'm not mistaken, what he's trying to say is that there could be a
system in which sizeof(void*) is different then sizeof(foo*).

Now I can't see how a pointer could be a different size for one type VS
another type.

I can't see how a system could possibly function that way.

You could have a system in which a local pointer is a different size
then a far pointer, however, it would still be the case that all local
pointer types would be the same size.

And I still don't see where in the standard, it speaks of the
possibility of pointers having different size for different types.

Nov 14 '05 #19
Flash Gordon wrote:

Dag-Erling Smørgrav wrote:
Flash Gordon <sp**@flash-gordon.me.uk> writes:
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.


Indeed.
I believe the point Pete was making,


I believe that Pete and I are in complete agreement.


I think so too.
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.


There are several cases where the standard allows you to assign a
pointer to another pointer type (some where a cast is required)
and you
are guaranteed to get what you would expect.
However, those cases don't
guarantee you can read that pointer (through another pointer) as a
pointer to a different type. Specifically, void* and char* are
guaranteed to have the same representation,
but pointers to structs are
not guaranteed to have the same representation as pointers to void.
Pointers to void are not
used to access anything; they are always cast or assigned to some
other pointer type before use.


Yes, but irrelevant to what we were discussing.


Here's the code again:

#define ALLOCATE2DARRAY(Type, x, y) \
(Type**)Allocate2DArray(sizeof(Type), x, y)

void **Allocate2DArray(int TypeSize, int x, int y)
{
void **ppi = malloc(x*sizeof(void*));
void *pool = malloc(x*y*TypeSize);
unsigned char *curPtr = pool;
int i;
for(i = 0; i < x; i++)
{
*(ppi + i) = curPtr;
curPtr += y*TypeSize;
}
return ppi;
}

ppi[0] is the first element in an array of pointer to void.
ppi[1] is the second element in an array of pointer to void.

After:
float **My2DFloat = ALLOCATE2DARRAY(float, x, y);

My2DFloat[0] is the first element in an array of pointer to float.

The difference of
(char *)&My2DFloat[1] - (char *)&My2DFloat[0]
is sizeof(float *) bytes

The difference of
(char *)&ppi[1] - (char *)&ppi[0]
is sizeof(void *) bytes

If sizeof (float *) does not equal sizeof (void *),
then My2DFloat[1] derferences the middle of a pointer.

--
pete
Nov 14 '05 #20
Axter wrote:
And I still don't see where in the standard, it speaks of the
possibility of pointers having different size for different types.


You interpret this as a guarantee
that all pointers have the same size?

N869
6.2.5 Types
[#27]

Pointers to other types need
not have the same representation or alignment requirements.

--
pete
Nov 14 '05 #21
pete wrote:
Axter wrote:
And I still don't see where in the standard, it speaks of the
possibility of pointers having different size for different types.


You interpret this as a guarantee
that all pointers have the same size?

N869
6.2.5 Types
[#27]

Pointers to other types need
not have the same representation or alignment requirements.

--
pete

It's actually in section #26.

After reading this section, I have to agree with you, in that it's
possible for a C compliant compiler to have sizeof(void*) not equal
sizeof(foo*)
I'm not aware of any such compiler, or system, but none the less, the
code is not portable as-is.

Nov 14 '05 #22
"Axter" <te**@axter.com> writes:
[...]
If I'm not mistaken, what he's trying to say is that there could be a
system in which sizeof(void*) is different then sizeof(foo*).
Yes.
Now I can't see how a pointer could be a different size for one type VS
another type.

I can't see how a system could possibly function that way.

You could have a system in which a local pointer is a different size
then a far pointer, however, it would still be the case that all local
pointer types would be the same size.
Imagine a system in which machine addresses point to words (where a
word is several octets), but you want to support 8-bit bytes. A word
pointer doesn't have enough information to specify a single byte, so
you invent an artificial byte pointer, consisting of a native word
pointer plus the offset of the byte within the word. Types void* and
char* would have to be implemented as a composite byte pointer, but
int* could be a (smaller) word pointer.

(The C implementation on Cray vector machines is very much like this,
except that the offset is stored in the unused upper bits of the
machine address. Types void* and char* have the same size but
different representations. The AS/400 is even more exotic, but I
don't remember the details.)
And I still don't see where in the standard, it speaks of the
possibility of pointers having different size for different types.


Why should it say so explictly? If it doesn't guarantee (explictly or
implicitly) that all pointers are the same size, it's legal for them
to be of different sizes.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #23
Keith Thompson <ks***@mib.org> writes:
[...]
Why should it say so explictly? If it doesn't guarantee (explictly or
implicitly) that all pointers are the same size, it's legal for them
to be of different sizes.


I seem to have invented a new word. Just to keep things simple, let's
assume that "explictly" is a synonym for "explicitly".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #24
Keith Thompson wrote:
(The C implementation on Cray vector machines is very much like this,
except that the offset is stored in the unused upper bits of the
machine address. Types void* and char* have the same size but
different representations.


"void* and char* have different representations" is not C.

--
pete
Nov 14 '05 #25
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
(The C implementation on Cray vector machines is very much like this,
except that the offset is stored in the unused upper bits of the
machine address. Types void* and char* have the same size but
different representations.


"void* and char* have different representations" is not C.


Oops. I meant void* and char* (which have the same representation)
vs. int* (which has a different representation). Thanks for catching
that.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #26

Barry Schwarz wrote:
On 1 May 2005 04:55:32 -0700, "Axter" <te**@axter.com> wrote:
[93 lines of quotes, some EIGHT deep, snipped]
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.

For future conversations, could you and Axter do everyone a favor and
learn how to trim your posts?

That was ridiculous.

Brian

Nov 14 '05 #27
On 1 May 2005 18:03:25 -0700, "Axter" <te**@axter.com> wrote:

Dag-Erling Smørgrav wrote:
Flash Gordon <sp**@flash-gordon.me.uk> writes:
> 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.


I don't think that's the point he was trying to make, because it would
not apply to the code I posted.
The code I posted has it cast to the target pointer via the macro.
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c

If I'm not mistaken, what he's trying to say is that there could be a
system in which sizeof(void*) is different then sizeof(foo*).

Now I can't see how a pointer could be a different size for one type VS
another type.

I can't see how a system could possibly function that way.


But the language standard is not constrained by the limits of your
imagination. If you want to write portable code, you don't make
assume any consistency that is not guaranteed by the standard. Look
at all the people who code
if x >= 'a' && x <= 'z'
because in ASCII the letters are contiguous.

You could have a system in which a local pointer is a different size
then a far pointer, however, it would still be the case that all local
pointer types would be the same size.

And I still don't see where in the standard, it speaks of the
possibility of pointers having different size for different types.


Only because you refuse to read the references already provided.
Section 6.2.5-27. Check the last sentence. The size of a pointer is
a part of how it represents its value.

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

<<Remove the del for email>>
Nov 14 '05 #28
On Mon, 02 May 2005 01:18:11 +0000, pete wrote:

....
Here's the code again:

#define ALLOCATE2DARRAY(Type, x, y) \
(Type**)Allocate2DArray(sizeof(Type), x, y)

void **Allocate2DArray(int TypeSize, int x, int y)
{
void **ppi = malloc(x*sizeof(void*));
void *pool = malloc(x*y*TypeSize);
unsigned char *curPtr = pool;
int i;
for(i = 0; i < x; i++)
{
*(ppi + i) = curPtr;
curPtr += y*TypeSize;
}
return ppi;
}
This looks fine, it allocates an array of x void * pointers and in effect
sets each of those to point to an array of y objects of TypeSize bytes
each.
ppi[0] is the first element in an array of pointer to void. ppi[1] is
the second element in an array of pointer to void.

After:
float **My2DFloat = ALLOCATE2DARRAY(float, x, y);
The cast in the macro is the source of potential problems from here on.
My2DFloat[0] is the first element in an array of pointer to float.
That is correct to a degree since we are assuming that float * and void *
have the same size. However the standard does NOT guarantee that float *
and void * use the same representation even if they have the same size.
What that means is that the void * values we've set the array up with are
not garanteed to be suitable to be accessed as float * values. We could
write new float * values to the array and then use those with no problem,
but we cannot portably access the existing void * values using My2DFloat,
unless we cast it back to void ** (or something similar). And "portable"
in that context is still based on our assumption about the sizes of void *
and float *.
The difference of
(char *)&My2DFloat[1] - (char *)&My2DFloat[0]
is sizeof(float *) bytes

The difference of
(char *)&ppi[1] - (char *)&ppi[0]
is sizeof(void *) bytes

If sizeof (float *) does not equal sizeof (void *), then My2DFloat[1]
derferences the middle of a pointer.


But code following this such as:

My2DFloat[0][0] = 0.0;

remains non-portable even if float * and void * have the same size,
because it is not converting between void * and float *, it is
reinterpreting the bit pattern of a void * as if it is a float *.

Lawrence
Nov 14 '05 #29


Lawrence Kirby wrote:
Here's the code again:

#define ALLOCATE2DARRAY(Type, x, y) \
(Type**)Allocate2DArray(sizeof(Type), x, y)

void **Allocate2DArray(int TypeSize, int x, int y)
{
void **ppi = malloc(x*sizeof(void*));
void *pool = malloc(x*y*TypeSize);
unsigned char *curPtr = pool;
int i;
for(i = 0; i < x; i++)
{
*(ppi + i) = curPtr;
curPtr += y*TypeSize;
}
return ppi;
}

This looks fine, it allocates an array of x void * pointers and in effect
sets each of those to point to an array of y objects of TypeSize bytes
each.


It also looks risky since one is assuming function malloc
will always return a pointer to storage, never returning
NULL.

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: Parrot | last post by:
I am trying to program a function to return a 2 dimensional array, but it's not working. I reduced the return value to 1 dimension and tested that to make sure that the problem wasn't elsewhere. ...
9
by: Luke Wu | last post by:
Hello, I'm having some problems understanding 2 dimensional arrays. My problem relates to the following code: #include <stdio.h> #define M 3 #define N 3
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
9
by: Dadi | last post by:
Hi, I can make a simple initialization work like this: Object ONE_ROW = {{"Vodafone", "5550160100197016"}}; But, now I want to create another array that consists of multiple copies of...
16
by: rguti | last post by:
Hi, How do I create a two dimensional array? I have created a one dimensional doing this: Dim laFields As ArrayList = New ArrayList How about to do a 2 dimensional?
5
by: Diffident | last post by:
Hello All, I have a 2-dimensional array that I am storing as a session variable. I have no idea on how I can cast the session variable back to 2-dimensional array. Any pointers? Reference...
4
by: entitledX | last post by:
Hi, I'm trying to use the HDF library to read a few HDF files that I need to process. The data in each file varies in rows, but the columns remain constant. Because of that, I had dynamically...
22
by: spam.noam | last post by:
Hello, I discovered that I needed a small change to the Python grammar. I would like to hear what you think about it. In two lines: Currently, the expression "x" is a syntax error. I suggest...
8
by: per9000 | last post by:
Hi all, I have a two-dimensional array of data, f.x int's. We can imagine that the array is "really large". Now I want the data in it and store this in a one-dimensional array. The obvious...
272
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.