Assuming size_t is unsigned long

P

Paulo Matos

Hello,

Is it safe to assume a size_t is an unsigned long? (is it forced by
the standard?)

Thank you,

Paulo Matos
 
R

Richard Heathfield

Paulo Matos said:
Hello,

Is it safe to assume a size_t is an unsigned long?

Only if it is an unsigned long, which it may well not be.
(is it forced by the standard?)

No, the Standard only requires that size_t be an unsigned integer type
(unsigned char, unsigned short, unsigned int, unsigned long, unsigned
long long if you have it) that can represent the size of any object. It
is not even required to be a standard unsigned integer type. It might,
for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;
 
B

B. Augestad

Richard said:
Paulo Matos said:




Only if it is an unsigned long, which it may well not be.




No, the Standard only requires that size_t be an unsigned integer type
(unsigned char, unsigned short, unsigned int, unsigned long, unsigned
long long if you have it) that can represent the size of any object. It
is not even required to be a standard unsigned integer type. It might,
for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;

From C99 §6.5.3.4 #20 :
"This requirement implicitly restricts size_t to be a synonym for an
existing unsigned integer type".

That rules out __internal_27_bit_integer_type, doesn't it?

Bjørn
 
R

Richard Heathfield

B. Augestad said:
Richard said:
[sizeof] might, for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;

From C99 §6.5.3.4 #20 :
"This requirement implicitly restricts size_t to be a synonym for an
existing unsigned integer type".

That rules out __internal_27_bit_integer_type, doesn't it?

I'm looking at C99, and 6.5.3.4 only goes up to para 7.

I checked n1124.pdf instead, and that goes up to 7 too.

And a search for "implicitly restricts size_t" fails to produce any
matches in either document.

So I don't know what you're talking about.
 
E

Eric Sosman

B. Augestad said:
From C99 §6.5.3.4 #20 :
"This requirement implicitly restricts size_t to be a synonym for an
existing unsigned integer type".

Where did you find this? ISO/IEC 9899:1999 (E) has a
section 6.3.5.4 (concerning the sizeof operator), but that
section has only seven paragraphs, not twenty-plus. Also,
Acrobat is unable to find the phrase "implicitly restricts"
anywhere in the document.
That rules out __internal_27_bit_integer_type, doesn't it?

Even if the passage is present and I've merely failed to
find it, I think __internal_27_bit_integer_type is allowed
anyhow. That type might also be known under other aliases
like uint27_t or uint_least25_t, which are (if they exist)
"integer types."
 
B

B. Augestad

Richard said:
B. Augestad said:

Richard said:
[sizeof] might, for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;

From C99 §6.5.3.4 #20 :
"This requirement implicitly restricts size_t to be a synonym for an
existing unsigned integer type".

That rules out __internal_27_bit_integer_type, doesn't it?


I'm looking at C99, and 6.5.3.4 only goes up to para 7.

I checked n1124.pdf instead, and that goes up to 7 too.

And a search for "implicitly restricts size_t" fails to produce any
matches in either document.

So I don't know what you're talking about.
I can see why, as I cannot find it myself right now. You see, I bought
the book version of the standard. The one bad thing about books is that
they aren't searchable. 6.5.3.4 was obviously way off, give me some time
to figure out what went wrong and browse through the book.

Bjørn.
 
B

B. Augestad

B. Augestad said:
Richard said:
B. Augestad said:

Richard Heathfield wrote:

[sizeof] might, for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;


From C99 §6.5.3.4 #20 :
"This requirement implicitly restricts size_t to be a synonym for an
existing unsigned integer type".

That rules out __internal_27_bit_integer_type, doesn't it?



I'm looking at C99, and 6.5.3.4 only goes up to para 7.

I checked n1124.pdf instead, and that goes up to 7 too.

And a search for "implicitly restricts size_t" fails to produce any
matches in either document.

So I don't know what you're talking about.
I can see why, as I cannot find it myself right now. You see, I bought
the book version of the standard. The one bad thing about books is that
they aren't searchable. 6.5.3.4 was obviously way off, give me some time
to figure out what went wrong and browse through the book.

Bjørn.
Found it!

I really scared myself for a while there, unable to locate the quote and
quietly wondering if I finally had gone insane. :)

The sentence is in §6.5.3.4, but not in the standard. The book version
consists of two parts, the C rationale and the C standard. I looked at
the wrong part, the rationale.

Sorry for the confusion this may have caused.
Bjørn
 
B

B. Augestad

Eric said:
Where did you find this? ISO/IEC 9899:1999 (E) has a
section 6.3.5.4 (concerning the sizeof operator), but that
section has only seven paragraphs, not twenty-plus. Also,
Acrobat is unable to find the phrase "implicitly restricts"
anywhere in the document.

Please see elsethread for an explanation of where I found it.
Even if the passage is present and I've merely failed to
find it, I think __internal_27_bit_integer_type is allowed
anyhow. That type might also be known under other aliases
like uint27_t or uint_least25_t, which are (if they exist)
"integer types."

So "existing" may mean existing in an implementation and not necessarily
existing in the C standard? Makes sense, I guess.

Bjørn
 
P

Paulo Matos

Paulo Matos said:



Only if it is an unsigned long, which it may well not be.


No, the Standard only requires that size_t be an unsigned integer type
(unsigned char, unsigned short, unsigned int, unsigned long, unsigned
long long if you have it) that can represent the size of any object. It
is not even required to be a standard unsigned integer type. It might,
for example, be defined like this:

typedef unsigned __internal_27_bit_integer_type size_t;

Well, I don't think there's a specific printf formatter for size_t,
right? So, how would you go about printing a size_t?
C FAQ says to use unsigned long... that's why I asked about size_t ==
unsigned long. That might be flawed since I may use %lu and size_t be
unsigned long long in the compiler. So, is there any portable way of
printing size_t?

Cheers,

Paulo Matos
 
G

Guest

Paulo said:
Well, I don't think there's a specific printf formatter for size_t,
right? So, how would you go about printing a size_t?

In C99, there is. You can use "%zu".
C FAQ says to use unsigned long... that's why I asked about size_t ==
unsigned long. That might be flawed since I may use %lu and size_t be
unsigned long long in the compiler. So, is there any portable way of
printing size_t?

C90 disallows a size_t greater than unsigned long. So, you can use
this:

size_t s;
/* ... */
#if __STDC_VERSION >= 199901L
printf("%zu", s);
#else
printf("%lu", (unsigned long) s);
#endif

It's probably best put in a helper function, rather than copying the
check everywhere.

(This will not work for implementations that use C99 syntax with a C90
library. Such implementations do not conform to any standard, but are
used in the real world. Decide for yourself whether you want to
support them.)
 
E

Eric Sosman

B. Augestad wrote On 04/09/07 08:46,:
Please see elsethread for an explanation of where I found it.




So "existing" may mean existing in an implementation and not necessarily
existing in the C standard? Makes sense, I guess.

That was one of the significant but largely unheralded
changes between C90 and C99. In C90, the "integer types"
were the basic nine: signed and unsigned char, short, int,
and long, plus plain char. C90 implementations were allowed
to provide additional exotic integer flavors, but any such
were not considered "integer types." Hence, the requirement
that size_t be an unsigned integer type meant that it could
not be one of the implementation's exotic additions.

C99 not only added the two long long variants to the
original suite of nine basic types, but also adopted language
(all that stuff about "rank") to allow exotic types to be
elevated to the status of "integer type." In effect, the
set of "integer types" became extensible, with rules in
place to govern the acceptable extensions. Types like size_t
are still described as "integer types," but the definition
now covers the exotic additions as well as the basic eleven.

Recently -- I think it was a week ago Sunday -- I read
that C0x plans to expand the integers further still. In
support of defensive programming, each of the eleven existing
types will gain a new "defensive" variant: "defensive signed
char," for example. The existing C90 types (retained for
backwards compatibility) will be known as "offensive." This
gives the programmer enough types to field a complete squad,
with the possibility of implementation-defined "special teams"
types in addition (subject to salary cap). The whole notion
is obviously rooted in American football and thus USA-centric,
but since all the internationalization stuff is already slated
for deletion this should surprise no one.

(Was it actually a week ago Sunday that I saw this? Yes,
I think it probably was ...)
 
P

Paulo Matos

In C99, there is. You can use "%zu".


C90 disallows a size_t greater than unsigned long. So, you can use
this:

size_t s;
/* ... */
#if __STDC_VERSION >= 199901L
printf("%zu", s);
#else
printf("%lu", (unsigned long) s);
#endif

It's probably best put in a helper function, rather than copying the
check everywhere.

(This will not work for implementations that use C99 syntax with a C90
library. Such implementations do not conform to any standard, but are
used in the real world. Decide for yourself whether you want to
support them.)


Didn't know about zu. Those are great news. Since I'm using std=c99 to
gcc I think I'll stick with zu. Thank you!
 
M

Martin Ambuhl

Paulo said:
Well, I don't think there's a specific printf formatter for size_t,
right?

Yes, there is: "%zu"
So, how would you go about printing a size_t?

With "%zu"
C FAQ says to use unsigned long... that's why I asked about size_t ==
unsigned long. That might be flawed since I may use %lu and size_t be
unsigned long long in the compiler. So, is there any portable way of
printing size_t?

If you don't have "%zu" available, use a specifier for an unsigned type
you do have and cast.

1) printf("sizeof c is \"%%zu\": %zu\n", sizeof c);

2) printf("sizeof c is \"%%lu\": %lu\n", (unsigned long) sizeof c);
 
R

Richard Heathfield

B. Augestad said:

I really scared myself for a while there, unable to locate the quote
and quietly wondering if I finally had gone insane. :)

Been there, done that, and all I got was this lousy T-shirt.
The sentence is in §6.5.3.4, but not in the standard. The book version
consists of two parts, the C rationale and the C standard. I looked at
the wrong part, the rationale.

And of course the Rationale is not normative, and even if it were it
wouldn't matter.
Sorry for the confusion this may have caused.

No sweat.
 
G

Guest

Richard said:
Harald van D?k said:



Chapter and verse, please.

size_t must be an unsigned integer type. In C90, implementation-
specific types are never integer types, even if they behave exactly
like integer types. In C99, the definition of integer types was
expanded to include implementation-defined integer types. (Sorry, no
exact C&V.)
 
R

Richard Heathfield

Harald van D?k said:
size_t must be an unsigned integer type.

That depends on whether "integer type" and "integral type" are
synonymous. I can find no justification in the Standard for this claim.

Relevant quotes:

3.3.3.4:

The value of the result is implementation-defined, and its type (an
unsigned integral type) is size_t defined in the <stddef.h> header.

4.1.5:
size_t

which is the unsigned integral type of the result of the sizeof
operator;


Yeah, I know this is bleeding-edge nit-picking, and no, I know it
doesn't actually matter either way, but being proved wrong here would
nevertheless be interesting and educational, at least for me.
(Actually, so would being proved right.)
 
G

Guest

Richard said:
Harald van D?k said:


That depends on whether "integer type" and "integral type" are
synonymous. I can find no justification in the Standard for this claim.

They are synonymous, see DR #067.
 
K

Keith Thompson

Paulo Matos said:
Didn't know about zu. Those are great news. Since I'm using std=c99 to
gcc I think I'll stick with zu. Thank you!

Be careful. gcc is just a compiler; the runtime library, including
the implementation of printf, is provided separately. On some
systems, printf will support "%zu"; on others, it won't, and gcc won't
necessarily know whether "%zu" is supported or not.

In a conforming implementation, the condition
__STDC_VERSION__ >= 199901L

(Harald, you missed the trailing "__") tells you that the entire
implementation is conforming. In real life, however, __STDC_VERSION__
is set by the compiler, independently of the runtime library.

C99 *discourages*, but does not forbid, making size_t bigger than
unsigned long. In C90, you can safely use:

printf("%lu", (unsigned long)sizeof whatever);

In C99, this will work *if* sizeof whatever happens not to exceed
ULONG_MAX. This will always be true if size_t is no bigger than
unsigned long; even if size_t is bigger than unsigned long, it will be
true if the particular size you're trying to print is no bigger than
ULONG_MAX.

If you want to be paranoid, writing code that will work even with
non-conforming implementations, you can do something like this
(untested):

size_t s = whatever;
if (s > (size_t)ULONG_MAX) {
printf("%zu", s);
}
else {
printf("%lu", (unsigned long)s);
}

That's not quite 100% safe either. It can fail if size_t is
*narrower* than unsigned long. It can also fail if size_t is wider
than unsigned long, but the runtime library doesn't support "%zu".

You can always write a function that converts a size_t value to a
string by brute force, without using the runtime library.
 

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

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top