sizeof void*

6 views
Skip to first unread message

Michael B. Allen

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
Hi!

If I write stack routines and want to push and pop pointers of any type, is
it portable/safe to accept a void * as the type passed to these functions?

void push( void *p )
void *pop()

More importantly, when creating the array used to store these pointers, how
would one allocate such an array? Is there any difference between these two
examples and are they portable/safe?

arry = malloc( sizeof( char * ) * SIZE )
arry = malloc( sizeof( int * ) * SIZE )

In general I would like any feedback on style or whatever. Below is my
sample proggie.

Thanks,
Mike

--

1 // t0.c
2
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #define SIZE 10
7
8 char **arry;
9 int sp = 0;
10
11 char *acharptr = "some text";
12
13 void
14 push( void *ptr ) {
15 arry[sp++] = ptr;
16 }
17
18 void*
19 pop() {
20 return arry[--sp];
21 }
22
23 int
24 main( int arc, char *argv[] ) {
25 arry = malloc( sizeof( char * ) * SIZE );
26 push( acharptr );
27 printf( "pushing: %s\n", acharptr );
28 printf( "popping: %s\n", (char *)pop() );
29 return 0;
30 }

[miallen@angus c]$ t0
pushing: some text
popping: some text


Ben Pfaff

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
"Michael B. Allen" <mballen@NOSPAM_erols.com> writes:

> If I write stack routines and want to push and pop pointers of any type, is
> it portable/safe to accept a void * as the type passed to these functions?

Sure.

> void push( void *p )
> void *pop()
>
> More importantly, when creating the array used to store these pointers, how
> would one allocate such an array?

void **array = malloc (sizeof *array * count);

> Is there any difference between these two
> examples and are they portable/safe?
>
> arry = malloc( sizeof( char * ) * SIZE )
> arry = malloc( sizeof( int * ) * SIZE )

The first allocates memory for an array of character pointers,
the latter for an array of integer pointers.

> 1 // t0.c

// is a C99-style comment, but there aren't any C99 compilers yet.

> 2
> 3 #include <stdio.h>
> 4 #include <stdlib.h>
> 5
> 6 #define SIZE 10
> 7
> 8 char **arry;

Why not void **?

> 9 int sp = 0;
> 10
> 11 char *acharptr = "some text";
> 12
> 13 void
> 14 push( void *ptr ) {
> 15 arry[sp++] = ptr;

I'd include an assertion to check for stack overflow.

> 16 }
> 17
> 18 void*
> 19 pop() {
> 20 return arry[--sp];

I'd include an assertion to check for stack underflow.

> 21 }
> 22
> 23 int
> 24 main( int arc, char *argv[] ) {

You know you don't have to declare those arguments if you're not
going to use them.

> 25 arry = malloc( sizeof( char * ) * SIZE );
> 26 push( acharptr );
> 27 printf( "pushing: %s\n", acharptr );
> 28 printf( "popping: %s\n", (char *)pop() );
> 29 return 0;
> 30 }

--
"Give me a couple of years and a large research grant,
and I'll give you a receipt." --Richard Heathfield

mike burrell

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
Michael B. Allen <mballen@nospam_erols.com> wrote:
> If I write stack routines and want to push and pop pointers of any type, is
> it portable/safe to accept a void * as the type passed to these functions?

as long as your only pushing and popping pointers to objects.

> 1 // t0.c


> 2
> 3 #include <stdio.h>
> 4 #include <stdlib.h>
> 5
> 6 #define SIZE 10
> 7
> 8 char **arry;

since you're dealing with pointers to void, why not make this void **?

> 9 int sp = 0;
> 10
> 11 char *acharptr = "some text";
> 12
> 13 void
> 14 push( void *ptr ) {
> 15 arry[sp++] = ptr;

> 16 }
> 17
> 18 void*
> 19 pop() {
> 20 return arry[--sp];

> 21 }
> 22
> 23 int
> 24 main( int arc, char *argv[] ) {

> 25 arry = malloc( sizeof( char * ) * SIZE );

arry = malloc(sizeof *arry * SIZE);
is the generally preferred style.

> 26 push( acharptr );
> 27 printf( "pushing: %s\n", acharptr );
> 28 printf( "popping: %s\n", (char *)pop() );

you don't need the cast here.

> 29 return 0;
> 30 }

otherwise your program looks very good.

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL,
/ \ AND NEWS TOO, dammit finger mik...@mikpos.dyndns.org for GPG key

Ben Pfaff

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
mike burrell <mik...@home.com> writes:

> > 18 void*
> > 19 pop() {
> > 20 return arry[--sp];
> > 21 }

[...]


> > 28 printf( "popping: %s\n", (char *)pop() );
>
> you don't need the cast here.

We had a long discussion of a similar topic around here (and
c.s.c) earlier: whether char * was okay as an argument
corresponding to %p. I don't recall that there was a definite
conclusion. As a result, I think it's safest to keep the cast.

[major snippage]
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz

mike burrell

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
Ben Pfaff <pfaf...@msu.edu> wrote:
> mike burrell <mik...@home.com> writes:
>> > 18 void*
>> > 19 pop() {
>> > 20 return arry[--sp];
>> > 21 }
> [...]
>> > 28 printf( "popping: %s\n", (char *)pop() );
>>
>> you don't need the cast here.

> We had a long discussion of a similar topic around here (and
> c.s.c) earlier: whether char * was okay as an argument
> corresponding to %p. I don't recall that there was a definite
> conclusion. As a result, I think it's safest to keep the cast.

good to keep in mind :)

Jack Klein

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
On 05 Aug 2000 16:48:57 -0400, Ben Pfaff <pfaf...@msu.edu> wrote in
comp.lang.c:

> mike burrell <mik...@home.com> writes:
>
> > > 18 void*
> > > 19 pop() {
> > > 20 return arry[--sp];
> > > 21 }
> [...]
> > > 28 printf( "popping: %s\n", (char *)pop() );
> >
> > you don't need the cast here.
>
> We had a long discussion of a similar topic around here (and
> c.s.c) earlier: whether char * was okay as an argument
> corresponding to %p. I don't recall that there was a definite
> conclusion. As a result, I think it's safest to keep the cast.
>

> [major snippage]

Actually James Kuyper did a pretty good job of settling this on
comp.std.c. Here's the relevant quote from section 6.2.5 of the final
C99 standard:

[#26] A pointer to void shall have the same representation
and alignment requirements as a pointer to a character
type.39)

Footnote 39 adds:

39)The same representation and alignment requirements are
meant to imply interchangeability as arguments to
functions, return values from functions, and members of
unions.

Jack Klein
--
Home: http://jackklein.home.att.net

Dan Pop

unread,
Aug 6, 2000, 3:00:00 AM8/6/00
to

>mike burrell <mik...@home.com> writes:
>
>> > 18 void*
>> > 19 pop() {
>> > 20 return arry[--sp];
>> > 21 }
>[...]
>> > 28 printf( "popping: %s\n", (char *)pop() );
>>
>> you don't need the cast here.
>
>We had a long discussion of a similar topic around here (and
>c.s.c) earlier: whether char * was okay as an argument
>corresponding to %p. I don't recall that there was a definite
>conclusion. As a result, I think it's safest to keep the cast.

There are two other reasons for keeping the cast:

1. Readability. It's weird to see a void * passed as argument to %s.
The cast says to the reader: "this is really a char pointer, stored in
in a void pointer".

2. gcc -Wall will complain about the argument mismatch.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

Michael B. Allen

unread,
Aug 6, 2000, 3:00:00 AM8/6/00
to

Dan Pop wrote in message ...

>2. gcc -Wall will complain about the argument mismatch.

Mine doesn't complain.

GCC VERSION:

Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.7.2.3/specs
gcc version 2.7.2.3

USAGE:

[miallen@angus c]$ gcc -Wall -g stack.o -o t2 t2.c

Morris M. Keesan

unread,
Aug 7, 2000, 3:00:00 AM8/7/00
to
On Sat, 05 Aug 2000 23:48:56 GMT, Jack Klein
<jack...@spamcop.net> wrote:
>On 05 Aug 2000 16:48:57 -0400, Ben Pfaff <pfaf...@msu.edu> wrote in
>comp.lang.c:
>
>> mike burrell <mik...@home.com> writes:
>>
>> > > 18 void*
>> > > 19 pop() {
>> > > 20 return arry[--sp];
>> > > 21 }
>> [...]
>> > > 28 printf( "popping: %s\n", (char *)pop() );
>> >
>> > you don't need the cast here.
>>
>> We had a long discussion of a similar topic around here (and
>> c.s.c) earlier: whether char * was okay as an argument
>> corresponding to %p. I don't recall that there was a definite
>> conclusion. As a result, I think it's safest to keep the cast.
>>
>> [major snippage]
>
>Actually James Kuyper did a pretty good job of settling this on
>comp.std.c. Here's the relevant quote from section 6.2.5 of the final
>C99 standard:
>
> [#26] A pointer to void shall have the same representation
> and alignment requirements as a pointer to a character
> type.39)
>
>Footnote 39 adds:
>
> 39)The same representation and alignment requirements are
> meant to imply interchangeability as arguments to
> functions, return values from functions, and members of
> unions.

My recollection is that comp.std.c never really arrived at
consensus on this. I think I was the first one to cite that
footnote, perhaps before the discussion moved from comp.lang.c to
comp.std.c, but the footnote is non-normative, and I don't
remember any agreement on whether there's any language in the
actual standard which says that the same representation and
alignment requirements really *do* mean interchangeability.

--
Morris M. Keesan -- mke...@lucent.com
Lucent Technologies Software Products Group

Dan Pop

unread,
Aug 7, 2000, 3:00:00 AM8/7/00
to

As it happens, I tried with 2.7.2.3, too, after removing the cast from
your program:

ues5:~/tmp 92> gcc -Wall test.c
test.c: In function `main':
test.c:28: warning: char format, void arg (arg 2)
ues5:~/tmp 93> gcc -v
Reading specs from /usr/local/lib/gcc-lib/alpha-dec-osf3.2/2.7.2.3/specs
gcc version 2.7.2.3

Reply all
Reply to author
Forward
0 new messages