different pointer sizes and representations

Discussion in 'C Programming' started by Luca Forlizzi, Nov 22, 2010.

  1. Hello,

    it is often remarked that pointer to objects and pointer to functions
    can have different representations and also different sizes. Are these
    the only possible differences or does the standard allows also
    pointers to distinct object types (or to distinct function types) to
    differ in representation and size (and alignment requirement, I
    suppose) ?

    Luca Forlizzi
     
    Luca Forlizzi, Nov 22, 2010
    #1
    1. Advertising

  2. Luca Forlizzi <> writes:
    > it is often remarked that pointer to objects and pointer to functions
    > can have different representations and also different sizes. Are these
    > the only possible differences or does the standard allows also
    > pointers to distinct object types (or to distinct function types) to
    > differ in representation and size (and alignment requirement, I
    > suppose) ?


    void* and pointers to character types have the same representation
    and alignment requirements.

    All pointers to struct types have the same representation and
    alignment requirements. (Note that this refers to the alignment
    of pointer objects, not the alignment of struct objects.)

    All pointers to union types have the same representation and
    alignment requirements.

    (I don't *think* pointer-to-struct and pointer-to-union types
    are required to have the same representation as each other, but
    I'm not certain.)

    There might be some guarantee regarding pointers to integer types
    that differ only in signedness, but I'm not sure about that.

    There are no other restrictions (beyond those that apply to scalar
    types in general).

    In most real-world implementations you're likely to encounter,
    all pointers have the same representation. In rare cases,
    pointer-to-function types might differ from pointer-to-object
    types; typically they'd be bigger. In other rare cases, void*
    and pointer-to-character types might differ from other object
    pointer types. But an implementation could legally make double*
    twice the size of int*.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 22, 2010
    #2
    1. Advertising

  3. Luca Forlizzi

    Tim Rentsch Guest

    Keith Thompson <> writes:

    > Luca Forlizzi <> writes:
    >> it is often remarked that pointer to objects and pointer to functions
    >> can have different representations and also different sizes. Are these
    >> the only possible differences or does the standard allows also
    >> pointers to distinct object types (or to distinct function types) to
    >> differ in representation and size (and alignment requirement, I
    >> suppose) ?

    >
    > void* and pointers to character types have the same representation
    > and alignment requirements.
    >
    > All pointers to struct types have the same representation and
    > alignment requirements. (Note that this refers to the alignment
    > of pointer objects, not the alignment of struct objects.)
    >
    > All pointers to union types have the same representation and
    > alignment requirements.
    >
    > (I don't *think* pointer-to-struct and pointer-to-union types
    > are required to have the same representation as each other, but
    > I'm not certain.)


    They are not so required.

    > There might be some guarantee regarding pointers to integer types
    > that differ only in signedness, but I'm not sure about that.


    Again there are not.

    > There are no other restrictions (beyond those that apply to scalar
    > types in general).


    Except, pointers to compatible types have the same representation
    and alignment requirements, and also qualified and non-qualified
    versions of pointers to compatible types.
     
    Tim Rentsch, Nov 23, 2010
    #3
  4. Luca Forlizzi

    Nobody Guest

    On Mon, 22 Nov 2010 09:17:16 -0800, Keith Thompson wrote:

    > In most real-world implementations you're likely to encounter, all
    > pointers have the same representation. In rare cases, pointer-to-function
    > types might differ from pointer-to-object types; typically they'd be
    > bigger.


    Or smaller. E.g. with DOS code, it was more common to have one code
    segment and multiple data segments (so a function pointer was just an
    offset but a data pointer was segment+offset) than the other way around.

    Also, on single-chip microcontrollers, you can typically have data in RAM,
    flash and/or EEPROM (with different code being required to access each
    type), but code can only go in flash. Usually, you would tag the pointer
    with a (non-standard) qualifier; occasionally you might use "unified"
    pointers (with the type stored in the pointer), but this makes for bloated
    code).
     
    Nobody, Nov 23, 2010
    #4
  5. On Mon, 22 Nov 2010 09:35:57 -0500, Luca Forlizzi
    <> wrote:

    > it is often remarked that pointer to objects and pointer to functions
    > can have different representations and also different sizes. Are these
    > the only possible differences or does the standard allows also
    > pointers to distinct object types (or to distinct function types) to
    > differ in representation and size (and alignment requirement, I
    > suppose) ?


    Pointers to different object types can definitely differ from each other.
    I've used systems where (char *)s differed in size and representation from
    all other pointers.

    I can't find anything in the standard which would prevent different
    function pointer types from having different sizes, etc.
    C99 6.3.2.3 paragraph 8 says, "A pointer to a function of one type may be
    converted to a pointer to a function of another type and back again; the
    result shall compare equal to the original pointer."


    --
    Morris Keesan --
     
    Morris Keesan, Nov 23, 2010
    #5
  6. Luca Forlizzi

    Tim Rentsch Guest

    "Morris Keesan" <> writes:

    > On Mon, 22 Nov 2010 09:35:57 -0500, Luca Forlizzi
    > <> wrote:
    >
    >> it is often remarked that pointer to objects and pointer to functions
    >> can have different representations and also different sizes. Are these
    >> the only possible differences or does the standard allows also
    >> pointers to distinct object types (or to distinct function types) to
    >> differ in representation and size (and alignment requirement, I
    >> suppose) ?

    >
    > Pointers to different object types can definitely differ from each other.
    > I've used systems where (char *)s differed in size and representation from
    > all other pointers.
    >
    > I can't find anything in the standard which would prevent different
    > function pointer types from having different sizes, etc.
    > C99 6.3.2.3 paragraph 8 says, "A pointer to a function of one type may be
    > converted to a pointer to a function of another type and back again; the
    > result shall compare equal to the original pointer."


    If two function types have the same return type, they
    are both compatible with a function type having the
    same return type but not specifying any parameter types
    (eg, like 'int foo()'), and so pointers to these two types
    must have the same size and representation, etc, since they
    both must match the common pointer type (eg, (int (*)(int))
    and (int (*)(float)) both must match (int (*)())).

    Pointers to functions not having the same return type don't
    have to be the same size etc.
     
    Tim Rentsch, Nov 23, 2010
    #6
  7. On Nov 23, 6:55 am, Tim Rentsch <> wrote:
    > "Morris Keesan" <> writes:
    >

    Say we've got a chip with the following architecture: a 256 byte RAM
    and a 65536 byte ROM, machine instructions accessing RAM through 8 bit
    offsets that differ from the machine instruction to access ROM. What
    dies that imply for pointer representation?
     
    Malcolm McLean, Nov 23, 2010
    #7
  8. Luca Forlizzi

    Eric Sosman Guest

    On 11/22/2010 11:55 PM, Tim Rentsch wrote:
    > "Morris Keesan"<> writes:
    >
    >> On Mon, 22 Nov 2010 09:35:57 -0500, Luca Forlizzi
    >> <> wrote:
    >>
    >>> it is often remarked that pointer to objects and pointer to functions
    >>> can have different representations and also different sizes. Are these
    >>> the only possible differences or does the standard allows also
    >>> pointers to distinct object types (or to distinct function types) to
    >>> differ in representation and size (and alignment requirement, I
    >>> suppose) ?

    >>
    >> Pointers to different object types can definitely differ from each other.
    >> I've used systems where (char *)s differed in size and representation from
    >> all other pointers.
    >>
    >> I can't find anything in the standard which would prevent different
    >> function pointer types from having different sizes, etc.
    >> C99 6.3.2.3 paragraph 8 says, "A pointer to a function of one type may be
    >> converted to a pointer to a function of another type and back again; the
    >> result shall compare equal to the original pointer."

    >
    > If two function types have the same return type, they
    > are both compatible with a function type having the
    > same return type but not specifying any parameter types
    > (eg, like 'int foo()'), and so pointers to these two types
    > must have the same size and representation, etc, since they
    > both must match the common pointer type (eg, (int (*)(int))
    > and (int (*)(float)) both must match (int (*)())).


    Like Morris Keesan, I can't find Standard language saying that
    the function pointers you mention are "compatible" in the sense that
    the Standard defines the word. "May be converted" and "compatible"
    aren't the same notion as I understand them; can you offer citations
    to clarify?

    Incidentally, note that an `(int (*)())' pointer and an
    `(int (*)(float))' pointer cannot call the same target function;
    one or the other is necessarily incorrect for the target.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 23, 2010
    #8
  9. Malcolm McLean <> writes:
    > On Nov 23, 6:55 am, Tim Rentsch <> wrote:
    >> "Morris Keesan" <> writes:
    >>

    > Say we've got a chip with the following architecture: a 256 byte RAM
    > and a 65536 byte ROM, machine instructions accessing RAM through 8 bit
    > offsets that differ from the machine instruction to access ROM. What
    > dies that imply for pointer representation?


    Assuming functions are in ROM, it implies that function pointers
    must be big enough to distinguish between any two functions in
    the program.

    If the implementation permitted no more than 255 functions, a
    function pointer could be implemented as an 8-bit index into a table.

    As for object pointers, I presume objects (at least constant ones)
    can be stored in either RAM or ROM, so again, an object pointer
    has to be big enough to distinguish between any two objects in
    the program. For example, a function could have a "const char*"
    parameter that points to an object that could be either in RAM
    or in ROM, so you can't get away with 8-bit RAM-only pointers.
    Using 8 bits for char* and 16 or more for const char* would be a
    clever trick, but I don't think it would be conforming.

    Then again, an implementation for such a small system is likely to
    have non-conforming extensions to deal with the small RAM.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 23, 2010
    #9
  10. Luca Forlizzi

    Seebs Guest

    On 2010-11-23, Malcolm McLean <> wrote:
    > Say we've got a chip with the following architecture: a 256 byte RAM
    > and a 65536 byte ROM, machine instructions accessing RAM through 8 bit
    > offsets that differ from the machine instruction to access ROM. What
    > dies that imply for pointer representation?


    That it is almost certainly non-conforming.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
     
    Seebs, Nov 23, 2010
    #10
  11. Luca Forlizzi

    Guest

    On Nov 22, 7:33 pm, Nobody <> wrote:
    > On Mon, 22 Nov 2010 09:17:16 -0800, Keith Thompson wrote:
    > > In most real-world implementations you're likely to encounter, all
    > > pointers have the same representation.  In rare cases, pointer-to-function
    > > types might differ from pointer-to-object types; typically they'd be
    > > bigger.

    >
    > Or smaller. E.g. with DOS code, it was more common to have one code
    > segment and multiple data segments (so a function pointer was just an
    > offset but a data pointer was segment+offset) than the other way around.



    Not that it really matters anymore, but medium model (multiple code
    segments, single data segment) was rather more commonly used than
    compact model (other way 'round).

    The reason was/is that multiple code segments were relatively easy and
    low cost to deal with (assuming a single function does not need to
    cross segment boundaries - and I never saw a compiler that allowed
    that), you just need to replace the near calls and returns with far
    ones, and adjust some offsets in the stack frames, which is basically
    trivial. Using multiple data segments needed continuous management of
    the segment registers, and usually brought a significant performance
    penalty.

    Most applications that needed multiple data segments ended up with
    either a hybrid model (mainly small or medium model, but with some
    "far" data, which required that that you explicitly mark some data
    pointers in your code "far," and then needed to take some care passing
    and converting pointers around), or as large model applications, where
    multiple code *and* data segments are allowed. 64KB of code was often
    restrictive anyway, so compact model just didn't match many
    requirements.
     
    , Nov 24, 2010
    #11
  12. Luca Forlizzi

    Tim Rentsch Guest

    Eric Sosman <> writes:

    > On 11/22/2010 11:55 PM, Tim Rentsch wrote:
    >> "Morris Keesan"<> writes:
    >>
    >>> On Mon, 22 Nov 2010 09:35:57 -0500, Luca Forlizzi
    >>> <> wrote:
    >>>
    >>>> it is often remarked that pointer to objects and pointer to functions
    >>>> can have different representations and also different sizes. Are these
    >>>> the only possible differences or does the standard allows also
    >>>> pointers to distinct object types (or to distinct function types) to
    >>>> differ in representation and size (and alignment requirement, I
    >>>> suppose) ?
    >>>
    >>> Pointers to different object types can definitely differ from each other.
    >>> I've used systems where (char *)s differed in size and representation from
    >>> all other pointers.
    >>>
    >>> I can't find anything in the standard which would prevent different
    >>> function pointer types from having different sizes, etc.
    >>> C99 6.3.2.3 paragraph 8 says, "A pointer to a function of one type may be
    >>> converted to a pointer to a function of another type and back again; the
    >>> result shall compare equal to the original pointer."

    >>
    >> If two function types have the same return type, they
    >> are both compatible with a function type having the
    >> same return type but not specifying any parameter types
    >> (eg, like 'int foo()'), and so pointers to these two types
    >> must have the same size and representation, etc, since they
    >> both must match the common pointer type (eg, (int (*)(int))
    >> and (int (*)(float)) both must match (int (*)())).

    >
    > [I am inverting the order of the response paragraphs.]
    >
    > Incidentally, note that an `(int (*)())' pointer and an
    > `(int (*)(float))' pointer cannot call the same target function;
    > one or the other is necessarily incorrect for the target.


    Sorry, you are absolutely right, it was a bad choice of example on
    my part -- it should have been (int (*)(int)) and (int (*)(double)),
    both being compatible with (int (*)()). My statement about which
    pointer-to-function types have the same representation should be
    modified accordingly, namely, pointers to functions that share a
    common compatible type are the ones that must have the same size,
    representation and alignment alignment requirements; more
    specifically, just having the same return type isn't enough - the
    parameter types must also be "suitable", which eliminates the pair
    of (int (*)(float)) and essentially any other type.

    Note that (int (*)(int)) and (int (*)(double)) are each compatible
    with (int (*)()), by 6.7.5.3p15.


    > Like Morris Keesan, I can't find Standard language saying that
    > the function pointers you mention are "compatible" in the sense that
    > the Standard defines the word. "May be converted" and "compatible"
    > aren't the same notion as I understand them; can you offer citations
    > to clarify?


    The (revised) pointer types are in fact not compatible, but what's
    relevant is that the function types they are pointing to share a
    common compatible type, because of 6.2.5p27, which reads in part:

    Similarly, pointers to qualified or unqualified versions of
    compatible types shall have the same representation and
    alignment requirements.

    Since each of the two types has the same representation etc as their
    shared compatible type, each must have the same representation etc
    as the other.

    The compatibility (which again isn't relevant, but...) of each of
    the function pointer types to the shared compatible type (int (*)())
    follows from 6.7.5.1p2, which talks about pointer types generally:

    For two pointer types to be compatible, both shall be
    identically qualified and both shall be pointers to
    compatible types.

    That a little better now?
     
    Tim Rentsch, Nov 24, 2010
    #12
  13. Tim Rentsch <> wrote:
    > If two function types have the same return type, they
    > are both compatible with a function type having the
    > same return type but not specifying any parameter types
    > (eg, like 'int foo()'), ...


    That's not true in the case of variadic functions. For
    instance, int (*)(int, ...) is not compatible with int (*)().

    --
    Peter
     
    Peter Nilsson, Nov 24, 2010
    #13
  14. Luca Forlizzi

    Tim Rentsch Guest

    Peter Nilsson <> writes:

    > Tim Rentsch <> wrote:
    >> If two function types have the same return type, they
    >> are both compatible with a function type having the
    >> same return type but not specifying any parameter types
    >> (eg, like 'int foo()'), ...

    >
    > That's not true in the case of variadic functions. For
    > instance, int (*)(int, ...) is not compatible with int (*)().


    Right, and I should have mentioned that. It is possible
    for two function types that are not compatible to be
    "similar" in that they require pointers to such types
    to have the same representation etc, but only if
    neither or both have ellipses.
     
    Tim Rentsch, Nov 24, 2010
    #14
  15. On 24 Nov, 07:23, Tim Rentsch <> wrote:
    > Peter Nilsson <> writes:
    > > Tim Rentsch <> wrote:
    > >> If two function types have the same return type, they
    > >> are both compatible with a function type having the
    > >> same return type but not specifying any parameter types
    > >> (eg, like 'int foo()'), ...

    >
    > > That's not true in the case of variadic functions. For
    > > instance, int (*)(int, ...) is not compatible with int (*)().

    >
    > Right, and I should have mentioned that.  It is possible
    > for two function types that are not compatible to be
    > "similar" in that they require pointers to such types
    > to have the same representation etc, but only if
    > neither or both have ellipses.


    If neither have ellipsis, then it is possibile that the two function
    types are both compatible with a "common" function type, which is not
    in prototype form. Then 6.2.5p27 applies, as you clearly explained in
    your reply to Eric Sosman.
    But if both have ellipsis, and are not compatible, I don't think there
    is a "common ancestor" in the compatibility relation. In which cases,
    and in the standard it is said that, pointers to such function types
    have the same represetation etc... ?
     
    Luca Forlizzi, Nov 25, 2010
    #15
  16. On 25 Nov, 10:53, Luca Forlizzi <> wrote:
    > On 24 Nov, 07:23, Tim Rentsch <> wrote:
    >
    > > Right, and I should have mentioned that.  It is possible
    > > for two function types that are not compatible to be
    > > "similar" in that they require pointers to such types
    > > to have the same representation etc, but only if
    > > neither or both have ellipses.

    >
    > If neither have ellipsis, then it is possibile that the two function
    > types are both compatible with a "common" function type, which is not
    > in prototype form. Then 6.2.5p27 applies, as you clearly explained in
    > your reply to Eric Sosman.
    > But if both have ellipsis, and are not compatible, I don't think there
    > is a "common ancestor" in the compatibility relation. In which cases,
    > and in the standard it is said that, pointers to such function types
    > have the same represetation etc... ?


    I answer to myself, of course Tim is right, cases of pairs of function
    types not compatible with each other but both compatible with a third
    type exist also when both function types have ellipsis.

    As an exercise, let C be the (binary) relation of compatibility
    between types. Let D be the binary relation between pairs (T1,T2) of
    types such that T1 and T2 are not compatibile, but type T0 exists that
    is compatible with both T1 and T2. (i.e. D = C^2 - C). So given
    (T1,T2) in D, another pair of types in D can be constructed as
    function types returning, respectively T1 and T2 and with identical
    parameters, or having T1 and T2 as corresponding parameters. And this
    function types can both have parameter type lists ending with
    ellipsis.

    For instance int [4] and int [5] form a pair in D, so as int (*)[4]
    and int (*)[5]. (incidentally, int (*)[4] and int (*)[5] are pointer
    to object types not compatible with each other but both required to
    have the same represetation and alignment requirments as int (*)[] and
    as int (*)[n] ).
    Then void (*pg1)( int, int (*)[4], ... ) and void (*pg2)( int, int (*)
    [5], ... ) are pointer to function types not compatible with each
    other but both required to have the same representation and alignment
    requirments as void (*pg0)( int n, int (*)[n], ... ).

    Similarly (considering the return types),
    int ( * (*pf1)(int, ...) )[4] and int ( * (*pf2)(int, ...) )[5]
    are pointer to function types not compatible with each other but both
    required to have the same representation and alignment requirments as
    int ( * (*)(int, ...) )[].
     
    Luca Forlizzi, Nov 30, 2010
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    34
    Views:
    13,784
    Oliver Wong
    Sep 12, 2005
  2. Peter Ammon
    Replies:
    5
    Views:
    2,822
    Old Wolf
    Aug 26, 2004
  3. Rade
    Replies:
    8
    Views:
    491
  4. Ganesh Gopalakrishnan
    Replies:
    1
    Views:
    151
    Ganesh Gopalakrishnan
    Oct 17, 2011
  5. Myth__Buster
    Replies:
    23
    Views:
    1,148
    Nobody
    Jun 26, 2012
Loading...

Share This Page