Portability regarding sizeof() function

Discussion in 'C Programming' started by Behzad, Apr 12, 2009.

  1. Behzad

    Behzad Guest

    Hi all,

    I am totally new to the field of portability. One point at the time of
    coding i thought would be problem in portability was the use of sizeof
    ().Now I have read some pages in the net about issues on the
    portability. After reading those pages and be assured that sizeof()
    can be dangerous,now i am preparing a solution. I was wondering if
    there are some best practices regarding sizeof() and Portability at
    all.

    Can anybody help me to get some solutions and practices?

    Thanks in advance,
    Behzad
    Behzad, Apr 12, 2009
    #1
    1. Advertising

  2. Behzad

    Ben Pfaff Guest

    Behzad <> writes:

    > I am totally new to the field of portability. One point at the time of
    > coding i thought would be problem in portability was the use of sizeof
    > ().Now I have read some pages in the net about issues on the
    > portability. After reading those pages and be assured that sizeof()
    > can be dangerous,now i am preparing a solution. I was wondering if
    > there are some best practices regarding sizeof() and Portability at
    > all.


    In what way can sizeof be dangerous? What pages make these
    claims?
    --
    Ben Pfaff
    http://benpfaff.org
    Ben Pfaff, Apr 12, 2009
    #2
    1. Advertising

  3. Behzad <> writes:
    > I am totally new to the field of portability. One point at the time of
    > coding i thought would be problem in portability was the use of sizeof
    > ().Now I have read some pages in the net about issues on the
    > portability. After reading those pages and be assured that sizeof()
    > can be dangerous,now i am preparing a solution. I was wondering if
    > there are some best practices regarding sizeof() and Portability at
    > all.
    >
    > Can anybody help me to get some solutions and practices?


    First off, sizeof is an operator, not a function.

    I'm not sure what you mean when you say that "sizeof() can be
    dangerous". For any type bigger than char, applying sizeof to that
    type will give you an implementation-defined result. It's guaranteed
    to be the actual size in bytes of that type, but that actual size can
    vary from one implementation to another. For example, sizeof(int)
    might be 2 on one system, 4 on another, or even 1 (if CHAR_BIT >= 16,
    which is common for DSPs).

    There is nothing inherently dangerous about the sizeof operator. It
    can be used in dangerous ways, but so can any feature of any language.

    Can you be more specific about your concerns?

    --
    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, Apr 12, 2009
    #3
  4. Behzad

    James Kuyper Guest

    Behzad wrote:
    > Hi all,
    >
    > I am totally new to the field of portability. One point at the time of
    > coding i thought would be problem in portability was the use of sizeof
    > ().Now I have read some pages in the net about issues on the
    > portability. After reading those pages and be assured that sizeof()
    > can be dangerous,now i am preparing a solution. I was wondering if
    > there are some best practices regarding sizeof() and Portability at
    > all.
    >
    > Can anybody help me to get some solutions and practices?


    Appropriate use of sizeof is essential to writing portable code. Example:

    struct tm *t = malloc(sizeof *t);

    Would you care to suggest a more portable way of doing that which
    doesn't involve use of the sizeof operator?

    Inappropriate use of sizeof can be dangerous, but then so can
    inappropriate use of just about any other feature of C.
    James Kuyper, Apr 12, 2009
    #4
  5. Behzad

    CBFalconer Guest

    James Kuyper wrote:
    >

    .... snip ...
    >
    > Appropriate use of sizeof is essential to writing portable code.
    > Example:
    > struct tm *t = malloc(sizeof *t);
    >
    > Would you care to suggest a more portable way of doing that which
    > doesn't involve use of the sizeof operator?
    >
    > Inappropriate use of sizeof can be dangerous, but then so can
    > inappropriate use of just about any other feature of C.


    Nit. I don't think that works. When sizeof is executed t has not
    yet been defined. I think it awaits the final semi.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Apr 13, 2009
    #5
  6. CBFalconer <> writes:

    > James Kuyper wrote:
    >>

    > ... snip ...
    >>
    >> Appropriate use of sizeof is essential to writing portable code.
    >> Example:
    >> struct tm *t = malloc(sizeof *t);
    >>
    >> Would you care to suggest a more portable way of doing that which
    >> doesn't involve use of the sizeof operator?
    >>
    >> Inappropriate use of sizeof can be dangerous, but then so can
    >> inappropriate use of just about any other feature of C.

    >
    > Nit. I don't think that works. When sizeof is executed t has not
    > yet been defined. I think it awaits the final semi.


    That is not so. I can't find the place where the standard states that
    an identifier is defined from the declarator onwards, but that has
    always been my understanding. I.e. even

    char c, *cp = &c;

    is valid.

    If you are right an I am wrong, I am in good company. gcc (and every
    other compiler I remember using) prints the size of one int here, not
    two:

    #include <stdio.h>

    int i[2];

    int main(void)
    {
    int i = sizeof i;
    printf("%d\n", i);
    return 0;
    }

    [The reason I am so sure about what compilers used to do is not a
    stellar one; I used to like to write code like this:

    char buffer[SOME_SIZE], *bp = buffer;

    when I needed some space and a pointer into it. I would never do that
    now, of course!]

    --
    Ben.
    Ben Bacarisse, Apr 13, 2009
    #6
  7. Behzad

    Behzad Guest

    Sorry for late response.

    Maybe instead of using 'dangerous', i should use another word!

    Anyway, when Let's explain more with an example:

    /*-------------------------------------------------------*/
    void somefunc(u8* resp,u8* buff)
    {
    u8* ptr = buff;

    ptr = *(int*)&resp[4];
    ptr += sizeof(float);

    ptr = *(int*)&resp[12];
    ptr += sizeof(int);

    ptr = *(int*)&resp[16];
    ptr += sizeof(short);

    }
    /*-------------------------------------------------------*/

    The above example should be able to run on x86 or ARM machine.Each
    machine could have Linux or Windows(XP,CE,etc...) installed on.
    so my concerns are the above codes that are ( in my opinion) highly
    dependent on the machine and OS implementations.
    Do also include Big-endian and Little-endian issues.

    Behzad
    Behzad, Apr 13, 2009
    #7
  8. CBFalconer <> writes:
    > James Kuyper wrote:
    >>

    > ... snip ...
    >>
    >> Appropriate use of sizeof is essential to writing portable code.
    >> Example:
    >> struct tm *t = malloc(sizeof *t);
    >>
    >> Would you care to suggest a more portable way of doing that which
    >> doesn't involve use of the sizeof operator?
    >>
    >> Inappropriate use of sizeof can be dangerous, but then so can
    >> inappropriate use of just about any other feature of C.

    >
    > Nit. I don't think that works. When sizeof is executed t has not
    > yet been defined. I think it awaits the final semi.


    Yes, it does work (though it took me a while to find the section in
    the standard that proves it).

    The object exists even before the declaration is reached. C99 6.2.4p4-5:

    An object whose identifier is declared with no linkage and without
    the storage-class specifier static has _automatic storage
    duration_.

    For such an object that does not have a variable length array
    type, its lifetime extends from entry into the block with which it
    is associated until execution of that block ends in any way.

    But the real question is the scope. C99 6.2.1p7 says:

    Structure, union, and enumeration tags have scope that begins just
    after the appearance of the tag in a type specifier that declares
    the tag. Each enumeration constant has scope that begins just
    after the appearance of its defining enumerator in an enumerator
    list. Any other identifier has scope that begins just after the
    completion of its declarator.

    In the declaration above:

    struct tm *t = malloc(sizeof *t);

    the declarator is ``*t'', the scope of t begins before the "=", and
    the initializer is valid.

    Incidentally, the fact that the lifetime of an automatic object starts
    on entry to the block, before the declaration itself is reached, has
    some interesting, though probably not very useful, consequences.

    #include <stdio.h>
    int main(void)
    {
    int i;
    for (i = 0; i <= 1; i ++) {
    int *foo_addr;
    if (i == 1) {
    printf("foo isn't visible yet, but its value is %d\n", *foo_addr);
    }
    int foo = 42;
    if (i == 0) {
    foo_addr = &foo;
    }
    }
    return 0;
    }

    The output is:

    foo isn't visible yet, but its value is 42

    --
    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, Apr 13, 2009
    #8
  9. Behzad

    Ben Pfaff Guest

    Keith Thompson <> writes:

    > Incidentally, the fact that the lifetime of an automatic object starts
    > on entry to the block, before the declaration itself is reached, has
    > some interesting, though probably not very useful, consequences.
    >
    > #include <stdio.h>
    > int main(void)
    > {
    > int i;
    > for (i = 0; i <= 1; i ++) {
    > int *foo_addr;
    > if (i == 1) {
    > printf("foo isn't visible yet, but its value is %d\n", *foo_addr);
    > }
    > int foo = 42;
    > if (i == 0) {
    > foo_addr = &foo;
    > }
    > }
    > return 0;
    > }


    I think you're missing an important fact here. The block that
    starts on the line of the "for" loop is exited just before i++ is
    evaluated, and then it is re-entered in the second iteration of
    the loop. Therefore, the value of foo_addr is indeterminate when
    *foo_addr is evaluated during the second iteration, and therefore
    this code yields undefined behavior.
    --
    "...Almost makes you wonder why Heisenberg didn't include postinc/dec operators
    in the uncertainty principle. Which of course makes the above equivalent to
    Schrodinger's pointer..."
    --Anthony McDonald
    Ben Pfaff, Apr 13, 2009
    #9
  10. Ben Pfaff <> writes:
    > Keith Thompson <> writes:
    >> Incidentally, the fact that the lifetime of an automatic object starts
    >> on entry to the block, before the declaration itself is reached, has
    >> some interesting, though probably not very useful, consequences.
    >>
    >> #include <stdio.h>
    >> int main(void)
    >> {
    >> int i;
    >> for (i = 0; i <= 1; i ++) {
    >> int *foo_addr;
    >> if (i == 1) {
    >> printf("foo isn't visible yet, but its value is %d\n", *foo_addr);
    >> }
    >> int foo = 42;
    >> if (i == 0) {
    >> foo_addr = &foo;
    >> }
    >> }
    >> return 0;
    >> }

    >
    > I think you're missing an important fact here. The block that
    > starts on the line of the "for" loop is exited just before i++ is
    > evaluated, and then it is re-entered in the second iteration of
    > the loop. Therefore, the value of foo_addr is indeterminate when
    > *foo_addr is evaluated during the second iteration, and therefore
    > this code yields undefined behavior.


    You're right, good catch.

    (It happened to "work" because both instances of foo, and of foo_addr,
    happen to have the "same" address. I put "same" in quotes because the
    addresses of the two instances can't be compared without invoking UB.)

    I could construct an example of the same thing that actually works
    using a goto, but I don't think I'll bother.

    --
    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, Apr 13, 2009
    #10
  11. Behzad

    BartC Guest

    "Behzad" <> wrote in message
    news:...

    > Anyway, when Let's explain more with an example:


    > void somefunc(u8* resp,u8* buff)
    > {
    > u8* ptr = buff;
    >
    > ptr = *(int*)&resp[4];
    > ptr += sizeof(float);
    >
    > ptr = *(int*)&resp[12];
    > ptr += sizeof(int);
    >
    > ptr = *(int*)&resp[16];
    > ptr += sizeof(short);
    >
    > }
    > /*-------------------------------------------------------*/


    Perhaps the examples can make more sense like this:

    ptr = *(float*)&resp[4];
    ptr += sizeof(float);

    ptr = *(int*)&resp[12];
    ptr += sizeof(int);

    ptr = *(short*)&resp[16];
    ptr += sizeof(short);


    > machine could have Linux or Windows(XP,CE,etc...) installed on.
    > so my concerns are the above codes that are ( in my opinion) highly
    > dependent on the machine and OS implementations.
    > Do also include Big-endian and Little-endian issues.


    Depends on where the resp[] array comes from. If from an outside source such
    as a file, then yes there could be all sorts of issues.

    If the resp is external and it's spec details exactly the type and width of
    the values it contains, then perhaps you're right and using sizeof(short)
    could be 'dangerous', if the machine's short is a different size from that
    specified for resp[].

    --
    Bartc
    BartC, Apr 13, 2009
    #11
  12. Behzad

    Behzad Guest


    > If the resp is external and it's spec details exactly the type and width of
    > the values it contains, then perhaps you're right and using sizeof(short)
    > could be 'dangerous',


    Thanks God someone got my point.
    I know this may cause a problem. What are your preferred solutions or
    practices?
    Behzad, Apr 13, 2009
    #12
  13. Behzad

    James Kuyper Guest

    Behzad wrote:
    >> If the resp is external and it's spec details exactly the type and width of
    >> the values it contains, then perhaps you're right and using sizeof(short)
    >> could be 'dangerous',

    >
    > Thanks God someone got my point.
    > I know this may cause a problem. What are your preferred solutions or
    > practices?


    It might help, perhaps, to provide a example showing your point which
    includes a function that does something not equivalent to {return;}, and
    which is placed in a context sufficiently well explained that we can
    figure out why it is a problem.
    James Kuyper, Apr 13, 2009
    #13
  14. Behzad

    James Kuyper Guest

    Behzad wrote:
    > Sorry for late response.
    >
    > Maybe instead of using 'dangerous', i should use another word!
    >
    > Anyway, when Let's explain more with an example:
    >
    > /*-------------------------------------------------------*/
    > void somefunc(u8* resp,u8* buff)
    > {
    > u8* ptr = buff;
    >
    > ptr = *(int*)&resp[4];
    > ptr += sizeof(float);
    >
    > ptr = *(int*)&resp[12];
    > ptr += sizeof(int);
    >
    > ptr = *(int*)&resp[16];
    > ptr += sizeof(short);


    buff is completely unused. ptr is set six times by that code, without
    having ever been used. somefunc() could be replaced by a nop. Whatever
    point you are trying to make has pretty much gotten lost by presenting a
    bad example

    > }
    > /*-------------------------------------------------------*/
    >
    > The above example should be able to run on x86 or ARM machine.Each
    > machine could have Linux or Windows(XP,CE,etc...) installed on.
    > so my concerns are the above codes that are ( in my opinion) highly
    > dependent on the machine and OS implementations.


    Code like "p += sizeof(int);" is indeed highly implementation-dependent.
    However, assuming that it is used in the right way, that very same
    dependency is precisely what enables the program as a whole to be
    portable, because it provides a way to compensate for the corresponding
    implementation-dependence of the size of an int.

    > Do also include Big-endian and Little-endian issues.


    Endianess is certainly an issue that can complicate the writing of
    portable code, but it's not clear what you want to say about it.
    James Kuyper, Apr 13, 2009
    #14
  15. Behzad

    Flash Gordon Guest

    Behzad wrote:
    >> If the resp is external and it's spec details exactly the type and width of
    >> the values it contains, then perhaps you're right and using sizeof(short)
    >> could be 'dangerous',

    >
    > Thanks God someone got my point.
    > I know this may cause a problem. What are your preferred solutions or
    > practices?


    If you are reading data where the specification says you have a number
    made up of two bytes in big-endian format then that is what you read.
    If, on the other hand, you want to know the size of a type or expression
    within the program you use sizeof. Two different problems with two
    different solutions.
    --
    Flash Gordon
    Flash Gordon, Apr 13, 2009
    #15
  16. Keith Thompson <> writes:
    <snip>
    > But the real question is the scope. C99 6.2.1p7 says:
    >
    > Structure, union, and enumeration tags have scope that begins just
    > after the appearance of the tag in a type specifier that declares
    > the tag. Each enumeration constant has scope that begins just
    > after the appearance of its defining enumerator in an enumerator
    > list. Any other identifier has scope that begins just after the
    > completion of its declarator.


    Thank you. You have no idea how hard I tried to find that wording!

    --
    Ben.
    Ben Bacarisse, Apr 13, 2009
    #16
  17. Behzad

    luserXtrog Guest

    On Apr 12, 11:40 pm, Han from China <>
    wrote:
    > Ben Bacarisse wrote:
    > > CBFalconer wrote:
    > >> Nit.  I don't think that works.  When sizeof is executed t has not
    > >> yet been defined.  I think it awaits the final semi.

    >
    > > That is not so.  I can't find the place where the standard states that
    > > an identifier is defined from the declarator onwards, but that has
    > > always been my understanding.  I.e. even

    >
    > >  char c, *cp = &c;

    >
    > > is valid.

    >
    > 6.2.1{7}.
    >
    > > If you are right an I am wrong

    >
    > If Chuck Falconer is right? Haha, good one. Not only is he wrong,
    > but he knows he's wrong. After all that's been seen on this
    > newsgroup, the only people not attributing disruptive intent to
    > Chuck Falconer are suckers, plain and simple.  


    And what intent does this post serve?

    --
    lxt
    luserXtrog, Apr 13, 2009
    #17
  18. Richard Heathfield <> writes:

    > CBFalconer said:
    >
    >> James Kuyper wrote:
    >>>

    >> ... snip ...
    >>>
    >>> Appropriate use of sizeof is essential to writing portable code.
    >>> Example:
    >>> struct tm *t = malloc(sizeof *t);
    >>>
    >>> Would you care to suggest a more portable way of doing that which
    >>> doesn't involve use of the sizeof operator?
    >>>
    >>> Inappropriate use of sizeof can be dangerous, but then so can
    >>> inappropriate use of just about any other feature of C.

    >>
    >> Nit. I don't think that works. When sizeof is executed t has not
    >> yet been defined. I think it awaits the final semi.

    >
    > How do you reconcile your opinion with what the Standard says in
    > 3.1.2.1 of C89 (or 6.2.1(4) of C99), given that the Standard's take
    > on the matter appears to be diametrically opposite to yours?


    The last sentence of 6.2.1(7) seems to be the operative one.

    It is a shame that the common case is documented as the exception at
    the end of a paragraph. I'd prefer a new paragraph for it, but that
    would require more words (but I say that only because I failed
    to notice it on more than one reading).

    --
    Ben.
    Ben Bacarisse, Apr 13, 2009
    #18
  19. Behzad

    BartC Guest

    "Richard Heathfield" <> wrote in message
    news:...
    > BartC said:
    >
    > <snip>
    >
    >> Perhaps the examples can make more sense like this:
    >>
    >> ptr = *(float*)&resp[4];
    >> ptr += sizeof(float);
    >>
    >> ptr = *(int*)&resp[12];
    >> ptr += sizeof(int);
    >>
    >> ptr = *(short*)&resp[16];
    >> ptr += sizeof(short);

    >
    > No, not really. It's still equivalent to a no-op once the function
    > returns.


    I didn't pay attention to the left-hand-sides, because I didn't think the
    function was supposed to do anything useful, other than provide a (not very
    good) example context for the use of sizeof.

    Looking at it more carefully, perhaps there was a point to it (copy some
    fields of resp to buff), although some pointer dereferences and casts are
    missing on the ptr= lines. Whether the use of sizeof is still questionable
    in this case depends on further info.

    --
    Bartc
    BartC, Apr 13, 2009
    #19
  20. luserXtrog <> writes:
    > On Apr 12, 11:40 pm, Han from China <>
    > wrote:

    [snip]
    >
    > And what intent does this post serve?


    He's a troll. I've found that killfiling him is a lot easier than
    trying to figure out his intent, if any.

    --
    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, Apr 13, 2009
    #20
    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. Derek
    Replies:
    7
    Views:
    24,304
    Ron Natalie
    Oct 14, 2004
  2. Trevor

    sizeof(str) or sizeof(str) - 1 ?

    Trevor, Apr 3, 2004, in forum: C Programming
    Replies:
    9
    Views:
    614
    CBFalconer
    Apr 10, 2004
  3. Vinu
    Replies:
    13
    Views:
    1,384
    Lawrence Kirby
    May 12, 2005
  4. blufox

    sizeof( int ) != sizeof( void * )

    blufox, May 22, 2006, in forum: C Programming
    Replies:
    2
    Views:
    543
    Joe Smith
    May 22, 2006
  5. venkat

    Regarding the sizeof a function

    venkat, Jun 15, 2007, in forum: C Programming
    Replies:
    17
    Views:
    485
    Richard Heathfield
    Jun 16, 2007
Loading...

Share This Page