Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sizeof(pointer)

23 views
Skip to first unread message

Neil Zanella

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to

Hello,

I have been wondering about whether or not all pointers take up
the same amount of space in memory. Surprisingly the following
test program seems to suggest that this might be the case:

#include <stdio.h>

main()
{
printf("sizeof(char *) is %d\n", sizeof(char *));
printf("sizeof(short *) is %d\n", sizeof(short *));
printf("sizeof(int *) is %d\n", sizeof(int *));
printf("sizeof(long *) is %d\n", sizeof(long *));
printf("sizeof(void *) is %d\n", sizeof(void *));
printf("sizeof(void **) is %d\n", sizeof(void **));
printf("sizeof(void ***) is %d\n", sizeof(void ***));
printf("sizeof(void ****) is %d\n", sizeof(void ****));
printf("sizeof(long double *) is %d\n", sizeof(long double *));
printf("sizeof(long double ***) is %d\n", sizeof(long double ***));
printf("sizeof(FILE *) is %d\n", sizeof(FILE *));
printf("sizeof(FILE **) is %d\n", sizeof(FILE **));

return 0;
}

In each case the size of the pointer was 4 when I compiled and ran the
program on a Linux box with gcc 2.7.2.3.

The C books I have looked at don't seem to say much about the result of
applying the sizeof operator to a pointer variable. Can someone please
provide some information and/or references on this issue?

Thanks,

Neil


mike burrell

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to
Neil Zanella <nzan...@cs.mun.ca> wrote:
> I have been wondering about whether or not all pointers take up
> the same amount of space in memory. Surprisingly the following
> test program seems to suggest that this might be the case:

> #include <stdio.h>

int


> main()
> {
> printf("sizeof(char *) is %d\n", sizeof(char *));

> printf("sizeof(FILE **) is %d\n", sizeof(FILE **));

to be pedantic, you should really cast the sizeof operator:
printf("sizeof(FILE **) is %d\n", (int)sizeof(FILE **));

> return 0;
> }

and why were you surprised? i think you need to take some time to learn
some machine language. pointers will become very clear after that.

remember that a pointer represents an area in memory. for nearly all
operations, the computer does not care whether the address in memory is an
int or a double. it would be very odd to have ints and doubles existing in
different address spaces. some computers that use a harvard architecture
may have pointers to functions be a different size than pointers to objects
(because code and data live in different address spaces), but even that
would be pretty rare, i would say.

anyway, knowing that all the pointers are of the same size doesn't buy you
anything because it's an error to assume that.

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL
/ \

Eric Sosman

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to
Neil Zanella wrote:
>
> Hello,

>
> I have been wondering about whether or not all pointers take up
> the same amount of space in memory. Surprisingly the following
> test program seems to suggest that this might be the case:

Such tests are largely useless, since they can only hope to
reveal the characteristics of a particular implementation. Here's
an analogy: I took a quick survey of my entire natal family and
found that all seven of us are right-handed. Should I conclude
that all people everywhere are right-handed?

By the way, your test program contains (multiple instances of)
an error, and could in principle output anything at all -- or even
"cause demons to fly out your nose." The problem is that the
sizeof operator produces a value of type size_t, but that the "%d"
printf() specifier requires a value of type int. On some machines
size_t and int may have the same representation and be passed to
functions in the same way, but this is not necessarily the case.
(It turns out that my entire family are American citizens; may I
conclude that nobody lives in Canada?) A better way to output a
size_t value is something like

printf ("sizeof(int*) = %lu\n", (unsigned long)sizeof(int*));

... the idea being that you don't really know what a size_t is and
hence you don't really know the appropriate conversion specifier, but
you *do* know how to convert a size_t to some other type for which
the conversion specifier *is* known. (As your knowledge increases,
you may eventually discover that this time-honored dodge ceases to
work as of the introduction of the new "C99" version of the Standard,
but that's a topic for some other time.)

----
Eric....@east.sun.com

Dave Vandervies

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to
In article <Pine.OSF.4.21.000605...@garfield.cs.mun.ca>,

Neil Zanella <nzan...@cs.mun.ca> wrote:
>
>Hello,
>
>I have been wondering about whether or not all pointers take up
>the same amount of space in memory. Surprisingly the following
>test program seems to suggest that this might be the case:
>
[test program to print sizes of pointers]

>
>In each case the size of the pointer was 4 when I compiled and ran the
>program on a Linux box with gcc 2.7.2.3.
>
>The C books I have looked at don't seem to say much about the result of
>applying the sizeof operator to a pointer variable. Can someone please
>provide some information and/or references on this issue?

A pointer needs to be wide enough to store the information needed to
find whatever it is that that pointer is pointing to; under Linux with
a flat 32-bit address space, pointers are all 32 bits. Under DOS, with
its segmented memory model, most pointers are 16 bits and point to an
offset within the current segment, while (if I remember correctly) far
pointers (which are used for out-of-segment data) are 32 bits and
contain both the segment address and the offset. Other architectures
have other (different) types and sizes of pointers, and don't all have
all types of pointers the same size. (Example? Anyone?) The only
requirement on sizes of pointers beyond that they're wide enough to
store enough information to determine what they're pointing at (with
the knowledge of the type of object) is that it can be determined with
sizeof.


dave

--
Dave Vandervies
dj3v...@student.math.uwaterloo.ca

This message made of 100% recycled electrons.

krishna

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to

Neil Zanella <nzan...@cs.mun.ca> wrote in message
news:Pine.OSF.4.21.000605...@garfield.cs.mun.ca...

>
> Hello,
>
> I have been wondering about whether or not all pointers take up
> the same amount of space in memory. Surprisingly the following
> test program seems to suggest that this might be the case:
>
> #include <stdio.h>

>
> main()
> {
> printf("sizeof(char *) is %d\n", sizeof(char *));
> printf("sizeof(short *) is %d\n", sizeof(short *));
> printf("sizeof(int *) is %d\n", sizeof(int *));
> printf("sizeof(long *) is %d\n", sizeof(long *));
> printf("sizeof(void *) is %d\n", sizeof(void *));
> printf("sizeof(void **) is %d\n", sizeof(void **));
> printf("sizeof(void ***) is %d\n", sizeof(void ***));
> printf("sizeof(void ****) is %d\n", sizeof(void ****));
> printf("sizeof(long double *) is %d\n", sizeof(long double *));
> printf("sizeof(long double ***) is %d\n", sizeof(long double ***));
> printf("sizeof(FILE *) is %d\n", sizeof(FILE *));

> printf("sizeof(FILE **) is %d\n", sizeof(FILE **));
>
> return 0;

> }
>
> In each case the size of the pointer was 4 when I compiled and ran the
> program on a Linux box with gcc 2.7.2.3.

Yes, AFAIK all pointers are allocated the same ammount of memory. But
how much is compiler dependent.

'krishna

>
> The C books I have looked at don't seem to say much about the result of
> applying the sizeof operator to a pointer variable. Can someone please
> provide some information and/or references on this issue?
>

> Thanks,
>
> Neil
>

Richard Heathfield

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to
krishna wrote:
>
> Neil Zanella <nzan...@cs.mun.ca> wrote in message
> news:Pine.OSF.4.21.000605...@garfield.cs.mun.ca...
> >
> > Hello,
> >
> > I have been wondering about whether or not all pointers take up
> > the same amount of space in memory. Surprisingly the following
> > test program seems to suggest that this might be the case:
> >
<snip program>

> >
> > In each case the size of the pointer was 4 when I compiled and ran the
> > program on a Linux box with gcc 2.7.2.3.
>
> Yes, AFAIK all pointers are allocated the same ammount of memory. But
> how much is compiler dependent.

Please point to the part of the ANSI C Standard which makes this clear.

(Hint: there is no such reference.)


--

Richard Heathfield

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.

C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
37 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (60
to go)

Richard Heathfield

unread,
Jun 5, 2000, 3:00:00 AM6/5/00
to
Eric Sosman wrote:
>
> By the way, your test program contains (multiple instances of)
> an error, and could in principle output anything at all -- or even
> "cause demons to fly out your nose." The problem is that the
> sizeof operator produces a value of type size_t, but that the "%d"
> printf() specifier requires a value of type int. On some machines
> size_t and int may have the same representation and be passed to
> functions in the same way, but this is not necessarily the case.

I thought size_t had to be an unsigned integer type. int is signed by
default. Therefore, they can't have the same representation, because int
has a sign bit and size_t doesn't.

(I know you know this already - just nit-picking really.)

> (It turns out that my entire family are American citizens; may I
> conclude that nobody lives in Canada?)

None of my family are USA citizens. Therefore, nobody lives in the USA.
This is a statistically significant result, based on a representative
sample.

> A better way to output a size_t value is something like
>
> printf ("sizeof(int*) = %lu\n", (unsigned long)sizeof(int*));

Quite so. It may soon become appropriate to output a size_t using a cast
to unsigned long long.

mike burrell

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
> Quite so. It may soon become appropriate to output a size_t using a cast
> to unsigned long long.

that would have to be one bigass struct (or array, i guess). boggles the
mind.

i'll probably get flamed for this, but i'll say here and now that:

printf("sizeof (void *) == %lu\n", (unsigned long)sizeof (void *));

will be safe for some years to come. i predict that there will not be a
machine to come into being (with a conforming C compiler) within the next
five years to have a pointer greater than 4.1e9 bytes in size. i'll even go
so far as to wager 10 canadian cents on it.

Mark A. Odell

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
On 5 Jun 2000 21:51:36 GMT, dj3v...@student.math.uwaterloo.ca (Dave
Vandervies) wrote:

>A pointer needs to be wide enough to store the information needed to
>find whatever it is that that pointer is pointing to; under Linux with
>a flat 32-bit address space, pointers are all 32 bits. Under DOS, with
>its segmented memory model, most pointers are 16 bits and point to an
>offset within the current segment, while (if I remember correctly) far
>pointers (which are used for out-of-segment data) are 32 bits and
>contain both the segment address and the offset. Other architectures
>have other (different) types and sizes of pointers, and don't all have
>all types of pointers the same size. (Example? Anyone?)

The Keil C51 for the 8051 has generic pointers with 3 bytes (one byte
used to signify which memory space is being pointed to (idata, data,
code, pdata, or xdata). With typed pointers they can be 1 or 2 bytes
as in the case of data and idata (one byte) or code and xdata (2 bytes).
It's all quite a pain.

Josep Monés i Teixidor

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
Hi,

If I'm not wrong, the standard says that pointers can always be converted to
void * except of function pointers which can only be converted to void * if
void * has enough bits.

I can only imagine different lenghts in a Harvard architecture (data and
code are addressed in separated memory maps). Does anyone know if PIC
microcontrollers do have this problem?

Regards,

Josep


Neil Zanella escribió en mensaje ...


>
>Hello,
>
>I have been wondering about whether or not all pointers take up
>the same amount of space in memory. Surprisingly the following
>test program seems to suggest that this might be the case:
>

>#include <stdio.h>
>
>main()
>{
> printf("sizeof(char *) is %d\n", sizeof(char *));
> printf("sizeof(short *) is %d\n", sizeof(short *));
> printf("sizeof(int *) is %d\n", sizeof(int *));
> printf("sizeof(long *) is %d\n", sizeof(long *));
> printf("sizeof(void *) is %d\n", sizeof(void *));
> printf("sizeof(void **) is %d\n", sizeof(void **));
> printf("sizeof(void ***) is %d\n", sizeof(void ***));
> printf("sizeof(void ****) is %d\n", sizeof(void ****));
> printf("sizeof(long double *) is %d\n", sizeof(long double *));
> printf("sizeof(long double ***) is %d\n", sizeof(long double ***));
> printf("sizeof(FILE *) is %d\n", sizeof(FILE *));
> printf("sizeof(FILE **) is %d\n", sizeof(FILE **));
>
> return 0;
>}
>

>In each case the size of the pointer was 4 when I compiled and ran the
>program on a Linux box with gcc 2.7.2.3.
>

Jack Klein

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
On Tue, 6 Jun 2000 03:20:01 +0200, "Josep Monés i Teixidor"
<jmo...@arrakis.es> wrote in comp.lang.c:

> Hi,
>
> If I'm not wrong, the standard says that pointers can always be converted to
> void * except of function pointers which can only be converted to void * if
> void * has enough bits.
>
> I can only imagine different lenghts in a Harvard architecture (data and
> code are addressed in separated memory maps). Does anyone know if PIC
> microcontrollers do have this problem?
>
> Regards,
>
> Josep

There is no guarantee that you can convert function pointers to void
pointers at all. It is undefined behavior, pure and simple. Has
nothing to do with the number of bits.

Don't know about the PIC, but as someone already pointed out earlier,
the lowly 8051 family, which vastly outsells the x86 family in units,
if not dollars, has a wonderful, quirky architecture that results in
various unusual pointer schemes from various compiler vendors.

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

Richard Heathfield

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
mike burrell wrote:
>
> Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
> > Quite so. It may soon become appropriate to output a size_t using a cast
> > to unsigned long long.
>
> that would have to be one bigass struct (or array, i guess). boggles the
> mind.
>
> i'll probably get flamed for this, but i'll say here and now that:
>
> printf("sizeof (void *) == %lu\n", (unsigned long)sizeof (void *));
>
> will be safe for some years to come. i predict that there will not be a
> machine to come into being (with a conforming C compiler) within the next
> five years to have a pointer greater than 4.1e9 bytes in size. i'll even go
> so far as to wager 10 canadian cents on it.

This shows a remarkable degree of confidence. Were I a betting man, I
would bet on the more likely of two outcomes. In the field of computing,
a historical perspective could lead one to believe that the more likely
of two outcomes is also the more outrageous of two outcomes.

Nevertheless, I was referring to outputting size_t in general, not
outputting sizeof(void *) in particular. For example, consider a filing
system, not so far into the future, on which the largest file size is
implementation-defined to be 1024 Gigabytes. So some bright bunny
decides to write a function to read a file into memory, and decides he
can do it all in one go:

unsigned char JohnnysLittleFile[1024 * 1024 * 1024 * 1024] = {0};

Now, what's sizeof(JohnnysLittleFile)?

That's a rhetorical question. No doubt it will attract one or two
rhetorical answers.

Keith Thompson

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
mike burrell <mik...@home.com> writes:
[...]

> remember that a pointer represents an area in memory. for nearly all
> operations, the computer does not care whether the address in memory is an
> int or a double. it would be very odd to have ints and doubles existing in
> different address spaces. some computers that use a harvard architecture
> may have pointers to functions be a different size than pointers to objects
> (because code and data live in different address spaces), but even that
> would be pretty rare, i would say.

One could easily have a system where a machine address is a word
pointer, an int* pointer is represented as a machine address (say, 32
bits), and a char* pointer is represented as a structure containing a
word pointer and an offset (say, 40, 48, or 64 bits). A void* pointer
would have to be compatible with a char* pointer. Converting an int*
to a void* would require expanding the pointer to the longer form and
setting the offset to 0.

I strongly suspect there are such systems, but I don't know of an
example off the top of my head. The Cray T90 *almost* does this. It
uses 64-bit pointers with a granularity of 64 bits, but since it
doesn't have a full 64-bit address space it's able to store the offset
information in the high-order bits of the word.

> anyway, knowing that all the pointers are of the same size doesn't
> buy you anything because it's an error to assume that.

Yes. In any case, the language provides enough mechanisms that you
don't *need* to assume that. If you need a generic pointer, use
void*. If you need to know how big a pointer is, use sizeof.

--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.

Marco Natoni

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
Neil,

Neil Zanella wrote:
> I have been wondering about whether or not all pointers take up
> the same amount of space in memory. Surprisingly the following
> test program seems to suggest that this might be the case:

[snip]

> The C books I have looked at don't seem to say much about the
> result of applying the sizeof operator to a pointer variable.
> Can someone please provide some information and/or references on
> this issue?

A pointer is just a number referring to a memory location, nothing of
extraordinary that its size does not vary according to the size of the
referred object.


Best regards,
Marco

Tarmo Samuel

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
"Josep Monés i Teixidor" wrote:

> I can only imagine different lenghts in a Harvard architecture (data and
> code are addressed in separated memory maps). Does anyone know if PIC
> microcontrollers do have this problem?
>

Depends, at least on the 16 series PICs there's no way to read a byte directly
from program memory; don't know about the others.

--
Tarmo Samuel
ta...@sisalik.ee

Eric Sosman

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
Richard Heathfield wrote:
>
> Eric Sosman wrote:
> >
> > By the way, your test program contains (multiple instances of)
> > an error, and could in principle output anything at all -- or even
> > "cause demons to fly out your nose." The problem is that the
> > sizeof operator produces a value of type size_t, but that the "%d"
> > printf() specifier requires a value of type int. On some machines
> > size_t and int may have the same representation and be passed to
> > functions in the same way, but this is not necessarily the case.
>
> I thought size_t had to be an unsigned integer type. int is signed by
> default. Therefore, they can't have the same representation, because int
> has a sign bit and size_t doesn't.

The signed and unsigned versions of a type must use the same
representation for the values they have in common, which in this
case is the range [0 .. min(INT_MAX, (size_t)-1)]. Yes, the O.P.
would have seen bizarre results if his machine's pointers had more
bytes than could be enumerated by an int, but as far as I know the
Deathstation 9000 is the only such machine. A more likely bizarre
result is that the program would have reported all pointer sizes as
zero.

In any event, it is incorrect to attempt to convert a size_t
value with a "%d" specifier. If the attempt appears to work, it's
only because of (un?)lucky coincidence. Murphy guarantees that the
attempt will fail only when it can cause the maximum damage.

----
Eric....@east.sun.com

Chris Torek

unread,
Jun 6, 2000, 3:00:00 AM6/6/00
to
In article <393c5...@news.arrakis.es>

Josep Monés i Teixidor <jmo...@arrakis.es> wrote:
>If I'm not wrong, the standard says that pointers can always be converted to
>void * except of function pointers which can only be converted to void * if
>void * has enough bits.

Well, more precisely, the C standard says nothing about converting
between "void *" and function pointers. One might hope it would work
if "void *" has enough bits, but there is no guarantee in the standard
(there may or may not be one in your implementations' documents).

>I can only imagine different lenghts in a Harvard architecture (data and
>code are addressed in separated memory maps).

Another relatively common reason to have different pointer lengths
lies in something called "descriptors". I believe descriptors, not
separate I&D, are the reason that the AS/400 has enormous (256 bit,
or 128 byte, or something) function pointers. The descriptor for
some function contains extra information needed to call that function.

Note that one can always add another level of indirection (at some
potential expense in performance) so that instead of pointing directly
to some function "f", one's data pointer points to the pointer that
points to "f". That is:

void *genptr;
int i = 3;
double d = 3.14159;
extern int somefn(int);

Now at this point, we can certainly write:

genptr = &i;

and:

genptr = &d;

but "genptr = somefn" is not at all safe. But suppose we write:

int (*fp)(int) = somefn;

genptr = &fp;

? This is guaranteed to work, and after casting "genptr" to the
type "pointer to (pointer to function of int returning int)", we
can get "fp" itself back, and then having "fp", we can call somefn():

(*(int (**)(int))genptr)(3);

This too is guaranteed to work!
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Bill Godfrey

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
Neil Zanella <nzan...@cs.mun.ca> writes:

> printf("sizeof(char *) is %d\n", sizeof(char *));
> printf("sizeof(short *) is %d\n", sizeof(short *));
> printf("sizeof(int *) is %d\n", sizeof(int *));

<snip>

Others have responded to your query directly, so I'll just bring
in a side issue...

You can do code like this more quickly and with less errors by
enlisting a bit of help from the pre-processor.

#define PRINTF_SIZEOF(type) printf("sizeof(" #type ") is %d.\n",sizeof(type))

/* ... */

PRINTF_SIZEOF(char*);
PRINTF_SIZEOF(short*);
PRINTF_SIZEOF(int*);

This will generate...

printf("sizeof(" "char*" ") is %d.\n",sizeof(char*));
printf("sizeof(" "short*" ") is %d.\n",sizeof(short*));
printf("sizeof(" "int*" ") is %d.\n",sizeof(int*));

Which is equivilent to...

printf("sizeof(char*) is %d.\n",sizeof(char*));
printf("sizeof(short*) is %d.\n",sizeof(short*));
printf("sizeof(int*) is %d.\n",sizeof(int*));

I found this technique useful when debugging a state machine...

#define RSTATE_CASE(state) case state: printf("In state " #state "\n"); break;
void report_state(state_t state)
{
switch (state)
{
RSTATE_CASE(STATE_SOMETHING)
RSTATE_CASE(STATE_SOMETHING_ELSE)
RSTATE_CASE(STATE_SOMETHING_FUNKY)
default: printf("In an unknown state (%d).\n,state); break;
}
}

So I get state names from the enum instead of the value at the end.

Bill, rambling about stuff that's beside the point.


-hs-

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
Bill Godfrey a écrit dans le message
<20000614.68...@bacchae.demon.co.uk.228.60.172>...

Nice shot. Thanks for the hint.

--
-hs-
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
"Learn to use your web search engine. Someday it may save your life.
Always keep your web search engine clean, dry, and serviceable."
--Dann Corbit CLC


Morris M. Keesan

unread,
Jun 15, 2000, 3:00:00 AM6/15/00
to
On 14 Jun 2000 23:35:19 +0100, Bill Godfrey <bill-g...@usa.net.invalid>
wrote:

>Neil Zanella <nzan...@cs.mun.ca> writes:
>
>> printf("sizeof(char *) is %d\n", sizeof(char *));
>> printf("sizeof(short *) is %d\n", sizeof(short *));
>> printf("sizeof(int *) is %d\n", sizeof(int *));
>
><snip>
>
>Others have responded to your query directly, so I'll just bring
>in a side issue...
>
>You can do code like this more quickly and with less errors by
>enlisting a bit of help from the pre-processor.
>
>#define PRINTF_SIZEOF(type) printf("sizeof(" #type ") is %d.\n",sizeof(type))
>

Which would be better defined as
printf("sizeof(" #type ") is %d.\n", (int)sizeof(type))
or
printf("sizeof(" #type ") is %lu.\n", (unsigned long)sizeof(type))
because we don't know what type size_t is, but we do know that it's not int,
which means that %d is not the correct format specifier for it.

But aside from that, this is a very nice use of the preprocessor.
--
Morris M. Keesan -- mke...@lucent.com
Lucent Technologies Software Products Group

0 new messages