size_t, when to use it? (learning)

Discussion in 'C Programming' started by G G, Apr 10, 2014.

  1. G G

    Ian Collins Guest

    The biggest gotcha I've been bitten by with size_t, being a typedef, is
    when using it for counters. No problem in a 64 bit build, but strange
    overflow errors in a 32 bit build.
     
    Ian Collins, Apr 11, 2014
    #21
    1. Advertisements

  2. G G

    Ian Collins Guest

    and see most of your applications slow down...
     
    Ian Collins, Apr 11, 2014
    #22
    1. Advertisements

  3. If the underlying address calculations are 64 bits, then passing about indices as 32 bits won't speed
    things up by much.
    Say we've got the following

    void payroll( struct Employee *employees, int N)
    {
    int i;

    for(i=0;i<N;i++)
    employees.paid = true;
    }

    Now at compile time, the compiler doesn't know that i * sizeof(struct Employee) won't go over 2GB.
    So it has to generate a 64 bit value anyway. The loop comparison can still be 32 bits, so you'll
    save something. But not as much as you might think.
     
    Malcolm McLean, Apr 11, 2014
    #23

  4. It is usual for hardware (unlike most high-level languages) to supply
    a multiply instruction where the product is twice as long as the
    multiplier and multiplicand. With both i and sizeof(struct Employee)
    in 32 bits, the multiply will generate a 64 bit product.

    Are there compilers that allow sizeof(struct) to go over 2GB?
    (That is, that will compile a struct that large?) In any case,
    the size is known at compile time.

    A large fraction of programs written will never have to process
    data over 2GB, though knowing which ones those are is important.

    No country will have more than 2 billion cities, no house more than
    2 billion doors or windows. No company more than 2 billion employees.
    No printer will print more than 2 billion characters on a line, no car
    will have more than 2 billion seats. There are plenty of things to
    count that won't get that big.

    -- glen
     
    glen herrmannsfeldt, Apr 11, 2014
    #24
  5. G G

    Ike Naar Guest

    You've tried to allocate space for N pointers-to-short ...


    .... but here you use the space as if it holds N shorts (assuming
    'potons' is a typo for 'photons').

    Did you mean

    short *photons = malloc(N * sizeof *short);

    ?
     
    Ike Naar, Apr 11, 2014
    #25
  6. You've mis-read the code. He's tried to allocate space for N shorts.


    No, sizeof *short is a syntax error.

    A better way to write the original would be:

    short *photons = malloc(N * sizeof *photons);

    but the "sizeof(short)" version is correct.
     
    Keith Thompson, Apr 11, 2014
    #26
  7. G G

    Martin Shobe Guest

    No he hasn't.


    I seriously doubt that would compile.

    Martin Shobe
     
    Martin Shobe, Apr 11, 2014
    #27
  8. We've discussed this many times in the past.
    My view is that the more natural readability of sizeof(short) outweighs
    the fact that you don't have to change the line if photons is changed to
    point to another type.
     
    Malcolm McLean, Apr 11, 2014
    #28
  9. G G

    Ike Naar Guest



    Yes I misread the code. Sorry for the confusion.
     
    Ike Naar, Apr 12, 2014
    #29
  10. G G

    Ike Naar Guest



    It won't compile. My mistake, I misread the malloc argument.
     
    Ike Naar, Apr 12, 2014
    #30
  11. G G

    Tim Rentsch Guest

    The type size_t is the type of the result of the sizeof operator,
    measuring a size in char-sized bytes of (the type of) its
    operand. In C11, the type size_t was chosen also for the result
    of the _Alignof operator, which is fairly natural even though
    what _Alignof is measuring is not exactly a size (though it is in
    units of char-sized bytes). On some platforms size_t is the same
    as unsigned int, but that's not true of all platforms. In most
    cases size_t is the same as either unsigned int or unsigned long,
    but the Standard doesn't require that.

    The only absolute rule for size_t is the one pointed out by James
    Kuyper, namely, when dealing with something that expects a
    pointer to size_t (eg, as a parameter or a return value), only
    that type [*] will work. Similarly this is true for pointers to
    pointers to size_t, etc. [*] The reason for the asterisk is to
    explain the variations related to void * and various qualified
    versions, eg, (const size_t *), but these are the same as for all
    other pointer types.

    Beyond that, any decision about using size_t is stylistic. For
    example, if size_t can hold the size of any object, then because
    an element of an array is always at least one byte a size_t value
    can hold the extent of the array, ie, the number of elements it
    has. This naturally suggests that size_t might be a good choice
    for variables meant to hold array extents, and this choice is
    used by many library functions. Similarly a size_t value might
    be used to keep a count of how many elements in an array satisfy
    a certain property, or a position within an array of an element
    that meets some criteria. All of these are plausible reasons for
    choosing size_t for certain uses, but again they are not
    absolute, not mandatory.

    An interesting question is whether to use size_t for variables
    used for indexing, eg, in for() loops. There are different
    schools of thought about whether such variables should be signed
    or unsigned. Obviously, if we want our index variables to be
    signed, size_t is not a workable choice.

    Personally, I avoid using size_t in most cases where there is a
    choice. My preference is to reserve size_t for only those
    places where what is being held is a size in bytes of some
    area of memory; using it for other purposes, eg, array extents
    or index variables, IMO makes code harder to understand rather
    than easier, and therefore should be avoided for that reason.
     
    Tim Rentsch, Apr 15, 2014
    #31
  12. G G

    Tim Rentsch Guest

    The point of having size_t is to decouple the choice of the
    result of the sizeof operator from choices made for other
    integer types. It is necessary to give implementations the
    freedom to make these choices independently. By itself size_t
    causes no problems - it causes problems only for people who
    insist on using it in ways beyond its original purpose.
     
    Tim Rentsch, Apr 15, 2014
    #32
  13. G G

    Tim Rentsch Guest

    This view is obviously at odds with the original motivation for
    having size_t in the first place. Cf. the Rationale document.
     
    Tim Rentsch, Apr 15, 2014
    #33
  14. G G

    Tim Rentsch Guest

    Do you think simply repeating your opinion, without offering
    any further explanation or justification, will have any effect
    on other people's reaction to it? For the better, I mean?
     
    Tim Rentsch, Apr 15, 2014
    #34
  15. G G

    Rosario193 Guest

    i agree
    i think better u32 or u16 but something one know range
    because of UB or more complex code that has to be with size_t
     
    Rosario193, Apr 15, 2014
    #35
  16. If I just said "I think you're wrong" you'd have a point. In fact I gave
    a brief justification. Anyone new to the group knows that there isn't a
    consensus that the sizeof *ptr method is superior to sizeof(type),
    without starting an entire sub-thread on the topic.
    Whether they agree with me of with Keith is up to them.
     
    Malcolm McLean, Apr 15, 2014
    #36
  17. Actually, it isn't. In the mentality of Kiki (and Kikian disciples, such
    as Tim), it is no more an individual choice than is the validity of the
    Trinity. Obviously, these sorts of decisions are made at the top and the
    rank-and-file is expected to go along. Dissent is not possible.
     
    Kenny McCormack, Apr 15, 2014
    #37
  18. G G

    Tim Rentsch Guest

    Actually I wasn't trying to make a point, just ask a question.
    I took your opinion to be "My view is that the more natural
    readability of sizeof(short) outweighs the fact that [etc]".
    I believed, perhaps wrongly, that you had stated this opinion
    before and were simply restating it (note, there was nothing
    further in the posting). Is that wrong? If so, my apologies.
     
    Tim Rentsch, Apr 18, 2014
    #38
  19. Yes, that's essentially it.
    There's no point starting essentially the same sub-thread every time someone
    posts a code snippet that contains a call to malloc(). OTOH newbies shouldn't
    be led to think that there's a consensus that the dereferencing style is
    to be recommended.
     
    Malcolm McLean, Apr 18, 2014
    #39
  20. william@wilbur.25thandclement.com wrote:

    (snip)
    Yes if you sizeof(type) someone could change the type, such that
    it didn't match.

    But one could also change the name such that it didn't match.

    There might have been:

    short *a;
    (... some lines in between)
    a=malloc(100*sizeof(*a));

    and someone later changes it to:

    short *a;
    long *b;
    (... some lines in between)
    b=malloc(100*sizeof(*a));

    Now, note that sizeof(*a) doesn't eliminate the possibility
    of bugs, but changes the ones that are possible.

    I can't tell which one a given person is more or less likely
    to do.

    -- glen
     
    glen herrmannsfeldt, Apr 19, 2014
    #40
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.