size_t, when to use it? (learning)

I

Ian Collins

G said:
typedef unsigned int size_t

..............

size_t

when to declare something size_t? when the variable is associated with memory usage?

at any other time should the variable be declared an unsigned int?

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.
 
I

Ian Collins

Malcolm said:
My view is that

size_t should be used consistently throughout a program for all index
variables and all counts of objects in memory.
It should be a fast integer type (normally easy to achieve).
It should be signed. If that means demanding special code for objects
of over half the address space, it's a price worth paying.
It should have a better name.

So call size_t "int" and make int 64 bits on a 64 bit machine,

and see most of your applications slow down...
 
M

Malcolm McLean

and see most of your applications slow down...
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.
 
G

glen herrmannsfeldt

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.

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
 
I

Ike Naar

Fixed-point numbers are integers to C, but that's just a reflection of the
fact that C doesn't have any native syntactical sugar for fixed-point
arithmetic.
The other question is whether

int i;
int N = 100000;
short *photons = malloc(N * sizeof(short));

You've tried to allocate space for N pointers-to-short ...
for(i=0;i<N;i++)
potons = detectphoton();


.... 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);

?
 
K

Keith Thompson

Ike Naar said:
You've tried to allocate space for N pointers-to-short ...

You've mis-read the code. He's tried to allocate space for N shorts.
for(i=0;i<N;i++)
potons = detectphoton();


... 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);

?


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.
 
M

Martin Shobe

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

No he hasn't.
for(i=0;i<N;i++)
potons = detectphoton();


... 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);


I seriously doubt that would compile.

Martin Shobe
 
M

Malcolm McLean

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.
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.
 
I

Ike Naar

Ike Naar said:
You've tried to allocate space for N pointers-to-short ...

You've mis-read the code. He's tried to allocate space for N shorts.
for(i=0;i<N;i++)
potons = detectphoton();


... 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);

?


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.


Yes I misread the code. Sorry for the confusion.
 
I

Ike Naar

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

No he hasn't.
for(i=0;i<N;i++)
potons = detectphoton();


... 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);


I seriously doubt that would compile.


It won't compile. My mistake, I misread the malloc argument.
 
T

Tim Rentsch

G G said:
typedef unsigned int size_t

.............

size_t

when to declare something size_t? when the variable is associated
with memory usage?

at any other time should the variable be declared an unsigned int?

it's not a question of style, right?

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.
 
T

Tim Rentsch

Malcolm McLean said:
typedef unsigned int size_t

size_t

when to declare something size_t? when the variable is associated
with memory usage? at any other time should the variable be
declared an unsigned int?

it's not a question of style, right?

It's partly a question of style.

My own view is that size_t should never have been introduced. It
causes far more problems than it solves. [snip elaboration]

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.
 
T

Tim Rentsch

Malcolm McLean said:
N1570 5.2.4.2.1 Sizes of integer types <limits.h>


Their implementation-defined values shall be equal or greater
in magnitude (absolute value) to those shown, with the same sign.

INT_MAX +32767

My view is that

size_t should be used consistently throughout a program for all
index variables and all counts of objects in memory.
It should be a fast integer type (normally easy to achieve).
It should be signed. [snip elaboration]

This view is obviously at odds with the original motivation for
having size_t in the first place. Cf. the Rationale document.
 
T

Tim Rentsch

Malcolm McLean said:
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.

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?
 
R

Rosario193

It's partly a question of style.

My own view is that size_t should never have been introduced. It causes far more problems than it
solves.
The original idea was that it would hold the size in bytes of an object in memory. Typically,
machines have an address space of 4GB. So if you want an object of over 2GB in size, you can't pass
an int to malloc(), as was the interface in old C.
But unfortunately the ANSI committee also used size_t for counts of objects in memory. If you have
a string of over 2GB, an int won't hold the length. sort also takes two size_ts.
But if your count of objects in memory is a size_t, then your index variable which goes from 0 to

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
 
M

Malcolm McLean

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?
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.
 
K

Kenny McCormack

Malcolm McLean said:
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.

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.
 
T

Tim Rentsch

Malcolm McLean said:
If I just said "I think you're wrong" you'd have a point.

Actually I wasn't trying to make a point, just ask a question.
In fact I gave a brief justification. [snip amplification]

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.
 
M

Malcolm McLean

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.
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.
 
G

glen herrmannsfeldt

[email protected] wrote:

(snip)
I've fixed several bugs in my career where people used `sizeof (type)',
where type was wrong. I've yet to encounter a similar bug where
people used `sizeof object'. Anecdotal, but the fact of the
matter is that `sizeof object' states more precisely what you
want, and precision is important when programming.
People keep repeating that rule for specific reasons, none of
which are to oppress you.

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

size_t, ssize_t and ptrdiff_t 56
size_t in a struct 24
Learning to programm 1
size_t in inttypes.h 4
Struggling With Learning to Application 2
return -1 using size_t??? 44
When/why to use size_t 12
usage of size_t 190

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top