470,848 Members | 1,336 Online

# size_t literals?

Hi!

On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?

TIA,
- J.
Feb 28 '08 #1
50 10858
ja************@gmail.com wrote:
On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?
Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

size_t x = 4294967296ULL;

Another possibility is to get 2^16 value and square it:

size_t x = (size_t)(1 << 16) * (size_t)(1 << 16);

and hope that the compiler will be able to simplify it and make it
a value instead of a run-time expression.

V
--
Feb 28 '08 #2
On 2008-02-28 09:32:01 -0800, ja************@gmail.com said:
>
Hi!

On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).
Presumably this was a warning. The compiler is obliged to convert the
value to a suitable type, despite the suffix, and your code should
work as you expect it to.
>
The nonstandard suffices "UI64" are also not recognized by the
compiler.
The future standard will use ULL, or any other mix of cases for those
three letters.
>
Should I construct with a value of 4294967295UL and then increment
the size_t variable?
No.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #3
ja************@gmail.com wrote in news:e6da1a2b-2561-4623-89a7-8303394cb7f9
>
Hi!

On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?

TIA,
- J.
What about the soon to be standard specifier of ULL? Otherwise, the math
method should work.

joe
Feb 28 '08 #4
On 2008-02-28 10:39:05 -0800, "Victor Bazarov" <v.********@comAcast.netsaid:
ja************@gmail.com wrote:
>On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?

Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?
Under the C99 rules and the C++0x rules, if unsigned long is too small
for a literal whose suffix is UL (i.e. unsigned long), the compiler
treats it as a literal of type unsigned long long. If unsigned long
long is too small, there's a problem, but in this case, it looks like
it's just what's needed.

The suffix tells the compiler the smallest type that you want; if the
value fits, you get that type. If the value is too large for that type,
you get a larger type. See [lex.icon]/2.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #5
Pete Becker wrote:
The future standard will use ULL, or any other mix of cases for those
three letters.
Will it guarantee that
sizeof(unsigned long long) sizeof(unsigned long)?

Or will ULL be defined as "postfix for literals with the same size as
size_t"? If not, why can't they define such a thing?
Feb 28 '08 #6
On Feb 28, 6:32 pm, jacek.dzied...@gmail.com wrote:
On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in
size_t x = 4294967296UL;
complains about the value being too large for unsigned long
(obviously, it's too large by one).
On a future conforming compiler, 4294967296ULL should do the
trick for this. Still, the next version of the standard will
allow size_t to be a typedef to an extended integral type, which
might well be longer than long long. And in that case, there is
no way you can simply create literals of that type (although
constant expressions are possible, e.g. (uintmax_t)1 << 200).

parts of it, as an extension, size_t can't be larger than
unsigned long, so there is no problem. (To tell the truth, I
can't imagine a compiler vendor being stupid enough not to make
long 64 bits if the hardware supported it.)
The nonstandard suffices "UI64" are also not recognized by the
compiler.
Should I construct with a value of 4294967295UL and then
increment the size_t variable?
You should be able to get around the problem with a constant
expression and a few casts, e.g. (uintmax_t)1 << 32, or some
such. (If the compiler doesn't support uintmax_t, then of
course, size_t can't be larger than unsigned long.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 28 '08 #7
Victor Bazarov wrote:
>
Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

There isn't such type under current ISO C++ 2003.
Feb 28 '08 #8
James Kanze wrote:
[..] (To tell the truth, I
can't imagine a compiler vendor being stupid enough not to make
long 64 bits if the hardware supported it.)
Just imagine Microsoft.
[..]
V
--
Feb 28 '08 #9
Ioannis Vranos wrote:
Victor Bazarov wrote:
>>
Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

There isn't such type under current ISO C++ 2003.
Yes, you're correct. There isn't. Neither would a double suffice
under the current standard (where only 6 digits of precision are
required for it). That's not the point. The OP's compiler may be
advanced enough beyond C++03 and/or provide unsigned long long as
an extension.

V
--
Feb 28 '08 #10
Pete Becker wrote:
On 2008-02-28 10:39:05 -0800, "Victor Bazarov" <v.********@comAcast.net>
said:
>ja************@gmail.com wrote:
>>On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?

Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

Under the C99 rules and the C++0x rules, if unsigned long is too small
for a literal whose suffix is UL (i.e. unsigned long), the compiler
treats it as a literal of type unsigned long long. If unsigned long long
is too small, there's a problem, but in this case, it looks like it's
just what's needed.

C99 is off topic, C++0x is not finalised and thus there is not any
"C++0x" conforming compiler, since it is not a standard yet.

I think the real answer for the OP size_t x= size_t(4294967296);

Of course this code is implementation-specific.
Feb 28 '08 #11
Victor Bazarov wrote:
Ioannis Vranos wrote:
>Victor Bazarov wrote:
>>Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

There isn't such type under current ISO C++ 2003.

Yes, you're correct. There isn't. Neither would a double suffice
under the current standard (where only 6 digits of precision are
required for it). That's not the point. The OP's compiler may be
advanced enough beyond C++03 and/or provide unsigned long long as
an extension.

AFAIK size_t being 64 bit and unsigned long being 32-bit, comply with
C++03. So he can just use

size_t(4294967296);
Of course this expression is implementation specific.
Feb 28 '08 #12
On 2008-02-28 11:26:48 -0800, "Victor Bazarov" <v.********@comAcast.netsaid:
Juha Nieminen wrote:
>Pete Becker wrote:
>>The future standard will use ULL, or any other mix of cases for those
three letters.

Will it guarantee that
sizeof(unsigned long long) sizeof(unsigned long)?

No, it will only guarangee

sizeof(unsigned long long) >= sizeof(unsigned long)
And, for pedancy's sake, it will require that unsigned long long is at
least 32 bits. Which doesn't respond to the question of whether it must
be larger than unsigned long, but completes what the standard will
require.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #13
On 2008-02-28 14:06:39 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
Pete Becker wrote:
>On 2008-02-28 10:39:05 -0800, "Victor Bazarov" <v.********@comAcast.netsaid:
>>ja************@gmail.com wrote:
On a machine where size_t is 64-bit, unsigned long is 32-bit, how
does one construct a size_t literal that says 2^32? Typing in

size_t x = 4294967296UL;

complains about the value being too large for unsigned long
(obviously, it's too large by one).

The nonstandard suffices "UI64" are also not recognized by the
compiler.

Should I construct with a value of 4294967295UL and then increment
the size_t variable?

Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?

Under the C99 rules and the C++0x rules, if unsigned long is too small
for a literal whose suffix is UL (i.e. unsigned long), the compiler
treats it as a literal of type unsigned long long. If unsigned long
long is too small, there's a problem, but in this case, it looks like
it's just what's needed.

C99 is off topic, C++0x is not finalised and thus there is not any
"C++0x" conforming compiler, since it is not a standard yet.
Nevertheless, the answer to this question lies, in part, in the C99 and
C++0x standards. Neither is off topic or irrelevant here.
>
I think the real answer for the OP size_t x= size_t(4294967296);

Of course this code is implementation-specific.
The original code should work just fine, as should your version. I see
nothing implementation-specific in yours.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #14
Pete Becker wrote:
On 2008-02-28 11:26:48 -0800, "Victor Bazarov"
<v.********@comAcast.netsaid:
>Juha Nieminen wrote:
>>Pete Becker wrote:
The future standard will use ULL, or any other mix of cases for
those three letters.

Will it guarantee that
sizeof(unsigned long long) sizeof(unsigned long)?

No, it will only guarangee

sizeof(unsigned long long) >= sizeof(unsigned long)

And, for pedancy's sake, it will require that unsigned long long is at
least 32 bits.
Not 64? Hmm in C99 unsigned long long int is (2^64 - 1)...
Which doesn't respond to the question of whether it
must be larger than unsigned long, but completes what the standard will
require.
V
--
Feb 28 '08 #15
Pete Becker wrote:
>
>I think the real answer for the OP size_t x= size_t(4294967296);

Of course this code is implementation-specific.

The original code should work just fine, as should your version.

Mine gives the feeling of a size_t constant.

I see
nothing implementation-specific in yours.

If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.
In my system for the code:
#include <iostream>
#include <cstddef>
int main(void)
{
using namespace std;

size_t x= size_t(4294967296);
cout<< x<< endl;
}
gives the compilation error:

[john@localhost src]\$ g++ main.cc -o foobar-cpp
main.cc:9: error: integer constant is too large for ‘long’ type
[john@localhost src]\$
while
#include <iostream>
#include <cstddef>
int main(void)
{
using namespace std;
cout<< numeric_limits<size_t>::max()<< endl;
}
gives:

[john@localhost src]\$ ./foobar-cpp
4294967295
[john@localhost src]\$

(The value that the OP wants minus 1).
Feb 28 '08 #16
On 2008-02-28 14:27:46 -0800, "Victor Bazarov" <v.********@comAcast.netsaid:
Pete Becker wrote:
>On 2008-02-28 11:26:48 -0800, "Victor Bazarov"
<v.********@comAcast.netsaid:
>>Juha Nieminen wrote:
Pete Becker wrote:
The future standard will use ULL, or any other mix of cases for
those three letters.

Will it guarantee that
sizeof(unsigned long long) sizeof(unsigned long)?

No, it will only guarangee

sizeof(unsigned long long) >= sizeof(unsigned long)

And, for pedancy's sake, it will require that unsigned long long is at
least 32 bits.

Not 64? Hmm in C99 unsigned long long int is (2^64 - 1)...
64 is right. Sorry.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #17
On 2008-02-28 14:34:24 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
>
If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.
Well, fine. If the value is too large to fit in a size_t, the code
won't work. There's nothing you can do about that. But that's not the
problem that was originally posed: size_t there is 64 bits.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #18
Pete Becker wrote:
On 2008-02-28 14:34:24 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
>>
If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.

Well, fine. If the value is too large to fit in a size_t, the code won't
work. There's nothing you can do about that. But that's not the problem
that was originally posed: size_t there is 64 bits.

The text that you quoted above explains why the code is
implementation-specific.
Feb 28 '08 #19
Ioannis Vranos wrote:
>
If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.
In my system for the code:
#include <iostream>
#include <cstddef>
int main(void)
{
using namespace std;

size_t x= size_t(4294967296);
cout<< x<< endl;
}
gives the compilation error:

[john@localhost src]\$ g++ main.cc -o foobar-cpp
main.cc:9: error: integer constant is too large for ‘long’ type
[john@localhost src]\$

Actually I think the above code should be:

#include <iostream>
#include <cstddef>
int main(void)
{
using namespace std;

size_t x= size_t(4294967296UL);
cout<< x<< endl;
}
Now the compiler gives the error message:

[john@localhost src]\$ g++ main.cc -o foobar-cpp
main.cc:9: error: integer constant is too large for ‘unsigned long’ type
[john@localhost src]\$
Feb 28 '08 #20
On 2008-02-28 15:12:17 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
Pete Becker wrote:
>On 2008-02-28 14:34:24 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
>>>
If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.

Well, fine. If the value is too large to fit in a size_t, the code
won't work. There's nothing you can do about that. But that's not the
problem that was originally posed: size_t there is 64 bits.

The text that you quoted above explains why the code is
implementation-specific.
No, it explains just the opposite: the question was how to write a
constant to initialize a 64-bit size_t. So the premise is not
satisfied, and no wrap around occurs. That's true on every system that
uses a 64-bit size_t.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 28 '08 #21
Pete Becker wrote:
On 2008-02-28 15:12:17 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
>Pete Becker wrote:
>>On 2008-02-28 14:34:24 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
If 4294967296 is larger than numeric_limits<size_t>::max(), then the
value will wrap around, if the code gets compiled.

Well, fine. If the value is too large to fit in a size_t, the code
won't work. There's nothing you can do about that. But that's not the
problem that was originally posed: size_t there is 64 bits.

The text that you quoted above explains why the code is
implementation-specific.

No, it explains just the opposite: the question was how to write a
constant to initialize a 64-bit size_t. So the premise is not satisfied,
and no wrap around occurs. That's true on every system that uses a
64-bit size_t.

An 64-bit size_t is an implementation specific issue. In other words,
the original question is about implementation-specific code, one that
provides unsigned long as a 32-bit type and size_t as a 64-bit type.
Feb 28 '08 #22
On 2008-02-28 15:33:35 -0800, Ioannis Vranos
<iv*****@nospam.no.spamfreemail.grsaid:
>
An 64-bit size_t is an implementation specific issue. In other words,
the original question is about implementation-specific code, one that
provides unsigned long as a 32-bit type and size_t as a 64-bit type.
Yes, exactly.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 29 '08 #23
On Feb 28, 11:09 pm, Ioannis Vranos
<ivra...@nospam.no.spamfreemail.grwrote:
Victor Bazarov wrote:
Ioannis Vranos wrote:
Victor Bazarov wrote:
Since the representation of 'size_t' is not dictated by the language,
you do what your implementation allows. If your 'size_t' is 64 bits,
then you need to find the type that would do what you need. Perhaps
a double. Maybe an unsigned long long?
There isn't such type under current ISO C++ 2003.
Yes, you're correct. There isn't. Neither would a double suffice
under the current standard (where only 6 digits of precision are
required for it). That's not the point. The OP's compiler may be
advanced enough beyond C++03 and/or provide unsigned long long as
an extension.
AFAIK size_t being 64 bit and unsigned long being 32-bit,
comply with C++03.
In C++03, size_t must be a typedef to an unsigned integral type.
The largest unsigned integral type is unsigned long, so size_t
cannot be larger than unsigned long.
So he can just use
size_t(4294967296);
Of course this expression is implementation specific.
And in C++03, it requires a diagnostic if long is less than 34
bits.

Note that at least in my environment, g++'s support for long
long is only partial: I can use long long, but the compiler will
not accept literals larger than long unless I explicitly suffix
them with LL or ULL. (Of course, if I add the options
-std=c++98 -pedantic, I don't have support for long long
either.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 29 '08 #24
James Kanze wrote:
In C++03, it must be a typedef to a standard unsigned integral
type: unsigned char, unsigned short, unsigned int or unsigned
long. There are no other choices. Which means that anything
you can represent with the suffix UL will fit in it.
Does that mean that the 64-bit version of MS Visual C++ breaks the
standard? If I'm not completely mistaken, it defines unsigned long to be
a 32-bit integral, but size_t to be 64-bit.
Feb 29 '08 #25
Victor Bazarov wrote:
in C99 unsigned long long int is (2^64 - 1)...
<pedantic mode>
Don't you mean "the maximum value which can be stored in an unsigned
long long int is (2^64 - 1)"?
</pedantic mode>
Feb 29 '08 #26
James Kanze wrote:
>AFAIK size_t being 64 bit and unsigned long being 32-bit,
comply with C++03.

In C++03, size_t must be a typedef to an unsigned integral type.
The largest unsigned integral type is unsigned long, so size_t
cannot be larger than unsigned long.

No, the largest unsigned *built in* type is unsigned long. size_t can be
larger than unsigned long. I just verified it by looking my K&R 2. Also,
the OP's compiler provides size_t as a 64-bit type and unsigned long as
a 32-bit type. If what you are saying was true, his compiler would be
broken.

>
>So he can just use
>size_t(4294967296);
>Of course this expression is implementation specific.

And in C++03, it requires a diagnostic if long is less than 34
bits.
I suppose you mean 32-bits.
Feb 29 '08 #27
James Kanze wrote:
>
Not here, since my (paper) copy of C90 is at home:-). But I did
look it up last night. I can't remember the exact words, but
basically, it must be a typedef to an unsigned integral type.

An implementation-defined unsigned integral type actually.

And C90 defines exactly four unsigned integral types, no more,
no less. Support for extended integral types was only added in
C99.

(In C++03, of course, all it says is that the definition is the
same as it is in C90.)

Yes, more precisely C++03 "contains" C95 (Amendment 1).

On page 1 of C++03:

"The library described in clause 7 of ISO/IEC 9899:1990 and clause 7 of
ISO/IEC 9899/Amd.1:1995 is hereinafter called the Standard C Library".
On page 325:

"Except as noted in clauses 18 through 27, the contents of each header
cname shall be the same as that of the corresponding header name.h, as
specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or
ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity, (Clause
7), as appropriate, as if by inclusion. In the C++ Standard Library,
however, the declarations and definitions (except for names which are
defined as macros in C) are within namespace scope (3.3.5) of the
namespace std".
Feb 29 '08 #28
Juha Nieminen wrote:
Victor Bazarov wrote:
>in C99 unsigned long long int is (2^64 - 1)...

<pedantic mode>
Don't you mean "the maximum value which can be stored in an unsigned
long long int is (2^64 - 1)"?
</pedantic mode>
Of course not. Any value of 'unsigned long long' type is precisely
(2^64 - 1) and any arithmetic operation yielding 'unsigned long long'
type also has the value of (2^64 - 1). No doubt. Sarcasm mode off.

V
--
Feb 29 '08 #29
On Feb 29, 2:31 pm, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
James Kanze wrote:
AFAIK size_t being 64 bit and unsigned long being 32-bit,
comply with C++03.
In C++03, size_t must be a typedef to an unsigned integral type.
The largest unsigned integral type is unsigned long, so size_t
cannot be larger than unsigned long.
No, the largest unsigned *built in* type is unsigned long.
What do you mean by "built in"? And what relevance does it have
here? The C++03 standard defines "integral type" as one of
bool, char, unsigned char, signed char, unsigned short, short,
unsigned int, int, unsigned long, long and wchar_t. That's an
exhaustive list. There aren't any more.

The C++0x standard will allow for "extended integral types",
which are implementation defined, but that's not the case of
C++03.
size_t can be larger than unsigned long. I just verified it by
looking my K&R 2.
That's not what ISO 9899:1990 says. And in this case, ISO
8988::1990 and ISO 14882::2003 are the defining word.
Also, the OP's compiler provides size_t as a 64-bit type and
unsigned long as a 32-bit type. If what you are saying was
true, his compiler would be broken.
Maybe. Maybe it already implements C++0x. (In the later case,
of course, it has long long, and he can use the postfix ULL for
what he wants.)
So he can just use
size_t(4294967296);
Of course this expression is implementation specific.
And in C++03, it requires a diagnostic if long is less than 34
bits.
I suppose you mean 32-bits.
No. I mean 34 bits. The value can't be represented in less
than 33 bits, and of course, it must fit into a long to be
legal, and a long also needs a bit for the sign, so it is only
legal (according to C++03) if long is at least 34 bits.

Dixit the standard. I think a lot of compilers are a bit less
rigorous here.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Feb 29 '08 #30
On Feb 29, 2:43 pm, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
James Kanze wrote:
Not here, since my (paper) copy of C90 is at home:-). But I did
look it up last night. I can't remember the exact words, but
basically, it must be a typedef to an unsigned integral type.
An implementation-defined unsigned integral type actually.
Probably. I don't remember exactly, but if it is implementation
defined, then an implementation must define which unsigned
integral type it uses.
And C90 defines exactly four unsigned integral types, no more,
no less. Support for extended integral types was only added in
C99.
(In C++03, of course, all it says is that the definition is the
same as it is in C90.)
Yes, more precisely C++03 "contains" C95 (Amendment 1).
On page 1 of C++03:
"The library described in clause 7 of ISO/IEC 9899:1990 and clause 7 of
ISO/IEC 9899/Amd.1:1995 is hereinafter called the Standard C Library".
On page 325:
"Except as noted in clauses 18 through 27, the contents of each header
cname shall be the same as that of the corresponding header name.h, as
specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or
ISO/IEC:1990 Programming Languages?C AMENDMENT 1: C Integrity, (Clause
7), as appropriate, as if by inclusion. In the C++ Standard Library,
however, the declarations and definitions (except for names which are
defined as macros in C) are within namespace scope (3.3.5) of the
namespace std".
Hmm. I don't have ammendment one available, but I don't think
it added the extended integral types. (I think that ammendment
1 is just bug fixes.) Even if it did, I'm not sure that it
changes anything. The "words" in the C standard still say that
it must be an unsigned integral type, and the definition of
unsigned integral type in C++03 is one of bool, char, signed
char, unsigned char, short, unsigned short, int, unsigned int,
long, unsigned long and wchar_t. (And wchar_t is required to be
exactly the same as one of the others, so it can't be larger
than unsigned long either.)

integral type, and the set of integral types is bound. And
implementation can't do just anything it feels like. (There was
a great deal of discussion in the C committee about the fact
that C99 broke an important promess in C: the fact that you
could cast any unsigned integral type to unsigned long, and
output it with printf using the format %lu. There was some
resistence to invalidating this guarantee.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 29 '08 #31
On Feb 29, 3:14 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Juha Nieminen wrote:
Victor Bazarov wrote:
in C99 unsigned long long int is (2^64 - 1)...
<pedantic mode>
Don't you mean "the maximum value which can be stored in an unsigned
long long int is (2^64 - 1)"?
</pedantic mode>
Of course not. Any value of 'unsigned long long' type is precisely
(2^64 - 1) and any arithmetic operation yielding 'unsigned long long'
type also has the value of (2^64 - 1). No doubt. Sarcasm mode off.
Wait a minute, Victor. I don't know what you're trying to say
(maybe that unsigned arithmetic is modulo 2^n, where n is the
number of bits), but what you've actually just said that any
(which in this context is more or less the same as all)
arithmetic operations which yield an unsigned long long has the
value 2^64-1. You don't really mean this: 1ULL + 1ULL certainly
doesn't have the value 2^64-1.

(And of course, the standard sets no upper limit on the size of
any type, and an implementation with char's of 1024 bits would
be conforming. Rather surprising, of course, but still
conforming. In which case, even an expression yielding an
unsigned char could have the value 2^1024-1.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 29 '08 #32
James Kanze wrote:
>
>No, the largest unsigned *built in* type is unsigned long.

What do you mean by "built in"? And what relevance does it have
here? The C++03 standard defines "integral type" as one of
bool, char, unsigned char, signed char, unsigned short, short,
unsigned int, int, unsigned long, long and wchar_t. That's an
exhaustive list. There aren't any more.

ptrdiff_t is also an implementation-defined, signed integer type.

>size_t can be larger than unsigned long. I just verified it by
looking my K&R 2.

K&R2 includes C89 towards the end of the book, and there, size_t is
mentioned as "implementation-defined".

No. I mean 34 bits. The value can't be represented in less
than 33 bits, and of course, it must fit into a long to be
legal, and a long also needs a bit for the sign, so it is only
legal (according to C++03) if long is at least 34 bits.

Can you mention the page of the C++03 where this is mentioned?
Feb 29 '08 #33
James Kanze wrote:
>
>ptrdiff_t is also an implementation-defined, signed integer type.

Not in C++03. It's a typedef to an implementation-defined,
signed integral type. Typedef does not create a new type.

That's what I meant, you are playing with the words here. :-)
Yes, but implementation defined contains limits.
No, it doesn't.
It [is] a typedef
to an implementation defined unsigned integral type.
which is not one of the built in types necessarily.
>>No. I mean 34 bits. The value can't be represented in less
than 33 bits, and of course, it must fit into a long to be
legal, and a long also needs a bit for the sign, so it is only
legal (according to C++03) if long is at least 34 bits.
>Can you mention the page of the C++03 where this is mentioned?

§2.13.1/2,3:

The type of an integer literal depends on its form,
value and suffix. If it is decimal and has no suffix,
it has the first of these types in which its value can
be represented: int, long int; if the value cannot be
represented as a long int, the behavior is
undefined.[...]

A program is ill-formed if one of its translation units
contains an integer literal that cannot be represented
by any of the allowed types.

(And yes, there is a blatent contradiction there. In the first
paragraph, it's undefined behavior, and in the second, the
program is ill-formed; i.e. requires a diagnostic. I've always
based my interpretation on this last paragraph.)

I do not see anything about 34 bits in the text you quoted.
Feb 29 '08 #34
Micah Cowan wrote:
>
James is quite correct that C++ has not made allowances for other
integer types. Which is probably an oversight on the part of the
standard's authors (and one which will be corrected in C++0x), but
that doesn't change the fact.

So an implementation-defined unsigned integer type is always one of the
4 built in unsigned integer types?

Feb 29 '08 #35
Pete Becker wrote:
[..] Implementation-defined can mean that
the implementation must choose something within stated constraints.
Well, the "stated constraints" are open to interpretation, AFAICS.
For example, [support.types]/3 in the C++0x draft says: "The macro
NULL is an implementation-defined C++ null pointer constant ..." The
phrase "implementation-defined" does not mean that the macro NULL
need not be a C++ null pointer constant. Similarly, an
"implementation-defined unsigned integer type" is an unsigned integer
type, as defined by the standard, and the choice of which one is up
to the implementation.
If the implementation provides additional unsigned integer types,
it can choose to make 'size_t' a synonym for one of those, and not
one of the four it _shall_ provide according to [basic.fundamental].
At least that's how I read the "implementation-defined" in this
particular case.

And if there is any doubt, here is the relevant quote:
[basic.fundamental]
2 "There are four signed integer types: ... ; the other signed
integer types are provided to meet special needs.

3 For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type: ..."

In my understanding, if the application chooses to provide the "other
signed integer types", it should also provide unsigned equivalents for
those.

Then, according to the 'size_t' definition, it is *absolutely free*
to make 'size_t' a typedef of one of those "other" unsigned integer
types, and /not/ limit itself to the four explicitly enumerated in
[basic.fundamental]/2 or /3.

V
--
Feb 29 '08 #36
James Kanze wrote:
On Feb 29, 3:14 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>Juha Nieminen wrote:
>>Victor Bazarov wrote:
in C99 unsigned long long int is (2^64 - 1)...
>><pedantic mode>
Don't you mean "the maximum value which can be stored in an unsigned
long long int is (2^64 - 1)"?
</pedantic mode>
>Of course not. Any value of 'unsigned long long' type is precisely
(2^64 - 1) and any arithmetic operation yielding 'unsigned long long'
type also has the value of (2^64 - 1). No doubt. Sarcasm mode off.

Wait a minute, Victor.
I believe Victor was wittily pointing out that what he meant by "2^64 -
interpretation was correct, but (as noted) pedantic. There ought to be
an emoticon for sarcasm. :)
Feb 29 '08 #37
On 2008-02-29 14:16:19 -0800, "Victor Bazarov" <v.********@comAcast.netsaid:
>
If the implementation provides additional unsigned integer types,
it can choose to make 'size_t' a synonym for one of those, and not
one of the four it _shall_ provide according to [basic.fundamental].
At least that's how I read the "implementation-defined" in this
particular case.
Yes, indeed. But the argument that Ioannis made was not that
"implementation-defined unsigned integral type" means any of the types,
including extended types, specified by the standard. Extended types
didn't exist in C90, and C++03 relies on C90.
>
And if there is any doubt, here is the relevant quote:
[basic.fundamental]
2 "There are four signed integer types: ... ; the other signed
integer types are provided to meet special needs.

3 For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type: ..."
Yes, those are extended integer types. They're new in C++0x, in large
part because C99 added them to C90.
>
In my understanding, if the application chooses to provide the "other
signed integer types", it should also provide unsigned equivalents for
those.

Then, according to the 'size_t' definition, it is *absolutely free*
to make 'size_t' a typedef of one of those "other" unsigned integer
types, and /not/ limit itself to the four explicitly enumerated in
[basic.fundamental]/2 or /3.
Yes, to one of those (if they exist). Not to an arbitrary made-up type.
The requirement is that it be one of the unsigned integral types, which
now includes extended integral types, provided that the implementation
provides them.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Feb 29 '08 #38
On Feb 29, 9:20 pm, Micah Cowan <mi...@cowan.namewrote:

[...]
C++03 quite clearly states that there are exactly four unsigned
integer types. Therefore, if an implementation were to choose a type
that were not one of those four, it would not, in fact, be an
"unsigned integer type", as defined by the standard.
The authors of the C++ standard quite clearly intend for the
fundamental types to remain 100% compatible with C. When C++98
was being written, C99 hadn't appeared yet; the wording in the
C++ standard reflects C90., which didn't have the extended
types.

The wording in C++0x reflects C99. (C++03 was just a bug fix
release, and didn't change anything fundamental.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Feb 29 '08 #39
On Feb 29, 11:16 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Pete Becker wrote:
[..] Implementation-defined can mean that
the implementation must choose something within stated constraints.
Well, the "stated constraints" are open to interpretation, AFAICS.
Not really.
For example, [support.types]/3 in the C++0x draft says: "The macro
NULL is an implementation-defined C++ null pointer constant ..." The
phrase "implementation-defined" does not mean that the macro NULL
need not be a C++ null pointer constant. Similarly, an
"implementation-defined unsigned integer type" is an unsigned integer
type, as defined by the standard, and the choice of which one is up
to the implementation.
If the implementation provides additional unsigned integer types,
If the type isn't described in §3.9.1, it isn't an "unsigned
integer type". The standard uses words in very strictly defined
senses, and in this case, it defines clearly what "unsigned
integer type" means in the standard in §3.9.1. An
implementation may define additional types (e.g. __uint64), and
these types may behave like unsigned integers, but they don't
meet the definition of "unsigned integer types" given in §3.9.1.
it can choose to make 'size_t' a synonym for one of those, and not
one of the four it _shall_ provide according to [basic.fundamental].
At least that's how I read the "implementation-defined" in this
particular case.
And if there is any doubt, here is the relevant quote:
[basic.fundamental]
2 "There are four signed integer types: ... ; the other signed
integer types are provided to meet special needs.
3 For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type: ..."
In my understanding, if the application chooses to provide the
"other signed integer types", it should also provide unsigned
equivalents for those.
I think you're missing a subtility of the English language. The
last clause in the sentence you quote from paragraph 2 has a
definite article. It's not talking about any old "other signed
integer types"; it's talking about those just mentionned (and
only those). The part you cut talked about int; this part talks
about the other signed integral types, to wit signed char,
signed short and signed long. And no others.

Note that all of this was longly discussed in the C committee
prior to C99. Before C99, there was an absolute guarantee that
long was the largest signed integer, and unsigned long the
largest unsigned integer. It was an important guarantee,
especially in C (think of printf), and the C committee didn't
break it lightly.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 1 '08 #40
"Victor Bazarov" <v.********@comAcast.netwrites:
Pete Becker wrote:
>[..] Implementation-defined can mean that
the implementation must choose something within stated constraints.

Well, the "stated constraints" are open to interpretation, AFAICS.
>For example, [support.types]/3 in the C++0x draft says: "The macro
NULL is an implementation-defined C++ null pointer constant ..." The
phrase "implementation-defined" does not mean that the macro NULL
need not be a C++ null pointer constant. Similarly, an
"implementation-defined unsigned integer type" is an unsigned integer
type, as defined by the standard, and the choice of which one is up
to the implementation.

If the implementation provides additional unsigned integer types,
it can choose to make 'size_t' a synonym for one of those, and not
one of the four it _shall_ provide according to [basic.fundamental].
At least that's how I read the "implementation-defined" in this
particular case.
Except that it's not possible for there to _be_ such a thing as
unsigned integer types that aren't provided by the Standard, since it
purports to define the set of "unsigned integer types" in
full. Therefore anything outside of that set is _not_ an unsigned
integer type, by the Standard's definition.

Using some other type than these four is no different than using a
float. Neither are "unsigned integer types".
And if there is any doubt, here is the relevant quote:
[basic.fundamental]
2 "There are four signed integer types: ... ; the other signed
integer types are provided to meet special needs.

3 For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type: ..."

In my understanding, if the application chooses to provide the "other
signed integer types", it should also provide unsigned equivalents for
those.
Except that "other", in this specific context, unambiguously means
"other than int", since it directly follows an explanation of "plain
ints". If this had been written by anyone else, I'd suspect you were

Note that, in all this, I'm speaking only of the actual text of the
Standard. I have my suspicions that this isn't what was actually
intended by the writers (you'd have to ask them); I think this is
especially likely since they appear to have remedied it for the
upcoming standard.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 1 '08 #41
James Kanze wrote:
The wording in C++0x reflects C99. (C++03 was just a bug fix
release, and didn't change anything fundamental.)
+ guarantying that the most containers allocate continuous memory space
and thus their members can also be accessed with regular pointers.
Mar 1 '08 #42
Ioannis Vranos wrote:
James Kanze wrote:
>The wording in C++0x reflects C99. (C++03 was just a bug fix
release, and didn't change anything fundamental.)

+ guarantying that the most containers allocate continuous memory
space and thus their members can also be accessed with regular
pointers.
Well, std::vector at least. From what I understand, that was the
intention all along. The committee just failed to write it down
explicitly in the 1998 release of the standard.
Mar 1 '08 #43
James Kanze wrote:
>
>K&R2 includes C89 towards the end of the book, and there, size_t is
mentioned as "implementation-defined".

Yes, but implementation defined contains limits. It a typedef
to an implementation defined unsigned integral type. It must be
an unsigned integral type. In §6.1.2.5 (C90): "There are four
signed integer types[...] For each signed integer type, there is
a corresponding (but different) unsigned integar type[...] "The
type char, the signed and unsigned integer types, and enumerated
types are collectively called integral types." And in the
above, "integral types" is in italics, which means that this is
the definition of the term (as used in the standard).

I verified what you said in clc for C90/C95 and it appears you are
right. Under C++03 any typedef of an implementation-defined
signed/unsigned integer type is a typedef of one of the 4 built in
signed/unsigned integer types respectively.

So, I think case is closed for this.
The "34-bits" issue remains open. AFAIK long is at least 32 bits, so I
can't get your reference that it is 34 bits at least.
Mar 1 '08 #44
On 1 mar, 01:40, Micah Cowan <mi...@cowan.namewrote:
"Victor Bazarov" <v.Abaza...@comAcast.netwrites:
Pete Becker wrote:
[...]
And if there is any doubt, here is the relevant quote:
[basic.fundamental]
2 "There are four signed integer types: ... ; the other signed
integer types are provided to meet special needs.
3 For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type: ..."
In my understanding, if the application chooses to provide the "other
signed integer types", it should also provide unsigned equivalents for
those.
Except that "other", in this specific context, unambiguously means
"other than int", since it directly follows an explanation of "plain
ints". If this had been written by anyone else, I'd suspect you were
Note that, in all this, I'm speaking only of the actual text of the
Standard. I have my suspicions that this isn't what was actually
intended by the writers (you'd have to ask them); I think this is
especially likely since they appear to have remedied it for the
upcoming standard.
Actually, I think it was intended. In 1990, long long and other
extended integral types weren't considered an issue.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 2 '08 #45
On 1 mar, 12:28, "Bo Persson" <b...@gmb.dkwrote:
Ioannis Vranos wrote:
James Kanze wrote:
The wording in C++0x reflects C99. (C++03 was just a bug fix
release, and didn't change anything fundamental.)
+ guarantying that the most containers allocate continuous memory
space and thus their members can also be accessed with regular
pointers.
Well, std::vector at least. From what I understand, that was the
intention all along. The committee just failed to write it down
explicitly in the 1998 release of the standard.
That's the justification:-). From what I understand, some of
the people who voted for the text of the original standard did
think this. IMHO, it's obviously an extension, but since
extensions weren't allowed in C++03, the committee "invented" an
original intent so that it could be considered a bug fix.
(IMHO, to consider it "original intent" would mean that the

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 2 '08 #46
On 1 mar, 13:12, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
James Kanze wrote:
[...]
The "34-bits" issue remains open. AFAIK long is at least 32
bits, so I can't get your reference that it is 34 bits at
least.
The 34 bits refered to being able to treat 4294967296 as a long
literal. Since the actual value here requires 33 bits to
represent, and long must have a bit for the sign as well, this
value can only be represented in a long if long has at least 34
bits.

According to the C++ standard, a decimal literal without a
suffix *must* be representable as a long, or an error occurs.
And in one place, the standard explicitly says that this error
makes the program ill-formed (which means that a diagnostic must
be issued).

This is, of course, an incompatibility with C, since C allows
unsigned long even for a decimal.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 2 '08 #47
James Kanze wrote:
>
This is, of course, an incompatibility with C, since C allows
unsigned long even for a decimal.

I did not understand your last sentence above.
Mar 2 '08 #48
On 2008-03-02 10:26:12, Ioannis Vranos wrote:
James Kanze wrote:
>>
This is, of course, an incompatibility with C, since C allows
unsigned long even for a decimal.

I did not understand your last sentence above.
"decimal integer literal"?

Gerhard
Mar 2 '08 #49
Ioannis Vranos <iv*****@nospam.no.spamfreemail.grwrites:
James Kanze wrote:
>>
This is, of course, an incompatibility with C, since C allows
unsigned long even for a decimal.

I did not understand your last sentence above.
He means that a decimal literal without one of the suffixes, that
specifies a number greater than LONG_MAX is undefined in C++ (which
requires it to be representable as a long), but not in C (incuding
C90), which allows (requires) it to be represented as an unsigned
long.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 2 '08 #50

### This discussion thread is closed

Replies have been disabled for this discussion.