size_t literals?

P

Pete Becker

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

Ioannis Vranos

Pete said:
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.
 
I

Ioannis Vranos

Ioannis said:
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]$
 
P

Pete Becker

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

Ioannis Vranos

Pete said:
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.
 
P

Pete Becker

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

James Kanze

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

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

James Kanze

James said:
[..]
There is no standard-defined literal of type 'std::size_t' because
it's not a fundamental type. 'std::size_t' is defined in <cstddef>.
It is most likely a typedef. Of course it can be a synonym to some
kind of implementation-specific type (like uint64_t), see the
compiler documentation.
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.
I can't see any proof of that. Could you please point me to the
relevant portion of the Standard that would state that 'size_t'
"must be a typedef to a standard unsigned ..." Thanks!

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

James Kanze

James said:
[..] (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.

I prefer not to:).

Seriously, the Microsoft compilers I've used all had size_t as a
32 bit quantity. Presumably, if and when Microsoft extends
their compiler to support 64 bit systems, both size_t and long
will become 64 bit quantities. Making long smaller than a
pointer will break a lot of code. (Admittedly already broken,
but that's not the point---it works with todays compilers.)
 
J

Juha Nieminen

James said:
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.
 
J

Juha Nieminen

Victor said:
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>
 
I

Ioannis Vranos

James said:
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.

And in C++03, it requires a diagnostic if long is less than 34
bits.

I suppose you mean 32-bits.
 
I

Ioannis Vranos

James said:
James said:
[..] (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.

I prefer not to:).

Seriously, the Microsoft compilers I've used all had size_t as a
32 bit quantity. Presumably, if and when Microsoft extends
their compiler to support 64 bit systems, both size_t and long
will become 64 bit quantities. Making long smaller than a
pointer will break a lot of code. (Admittedly already broken,
but that's not the point---it works with todays compilers.)


What relationship there is between size_t and "Making long smaller than
a pointer"? How can you compare a pointer with long? You can only
compare long with ptrdiff_t.
 
I

Ioannis Vranos

Ioannis said:
James said:
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.

I prefer not to:).

Seriously, the Microsoft compilers I've used all had size_t as a
32 bit quantity. Presumably, if and when Microsoft extends
their compiler to support 64 bit systems, both size_t and long
will become 64 bit quantities. Making long smaller than a
pointer will break a lot of code. (Admittedly already broken,
but that's not the point---it works with todays compilers.)


What relationship there is between size_t and "Making long smaller than
a pointer"? How can you compare a pointer with long? You can only
compare long with ptrdiff_t.


with ptrdiff_t being also an implementation-defined built in type, and
thus can be larger than long.
 
I

Ioannis Vranos

Correction:


Ioannis said:
Ioannis said:
James said:
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.

I prefer not to:).

Seriously, the Microsoft compilers I've used all had size_t as a
32 bit quantity. Presumably, if and when Microsoft extends
their compiler to support 64 bit systems, both size_t and long
will become 64 bit quantities. Making long smaller than a
pointer will break a lot of code. (Admittedly already broken,
but that's not the point---it works with todays compilers.)


What relationship there is between size_t and "Making long smaller
than a pointer"? How can you compare a pointer with long? You can only
compare long with ptrdiff_t.

==> with ptrdiff_t being also an *implementation-defined type*, and
 
V

Victor Bazarov

Juha said:
<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
 
V

Victor Bazarov

James said:
James said:
[..] (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.

I prefer not to:).

Seriously, the Microsoft compilers I've used all had size_t as a
32 bit quantity. Presumably, if and when Microsoft extends
their compiler to support 64 bit systems,

So, the fact that they "support" Windows XP x64 and Windows Vista
x64 editions doesn't count? Are you expecting them to "support"
64-bit Solaris? Or AIX? Or HP-UX? Or Linux? Or Tru64 Unix?

Seriously, they have had a 64 bit compiler as long as they had
a 64-bit OS, several years now. And, yes, imagine that on x64
Windows 'long' is still 32 bits and 'size_t' is 64 bits.
both size_t and long
will become 64 bit quantities. Making long smaller than a
pointer will break a lot of code. (Admittedly already broken,
but that's not the point---it works with todays compilers.)

I am not sure whether you want to, but you might, read about
why Microsoft did *not* make their 'long' 64 bits on Windows
x64. It's amusing. They claim backward compatibility, i.e.
they did not want to break any existing code...

V
 
I

Ioannis Vranos

Victor said:
I am not sure whether you want to, but you might, read about
why Microsoft did *not* make their 'long' 64 bits on Windows
x64. It's amusing. They claim backward compatibility, i.e.
they did not want to break any existing code...

The same stupid "reasons" we will get stuck with long long and is
unsigned equivalent.

Code considering that long is 32-bits exactly, without checking
numeric_limits of <limits>, or <climits> values first, is aimed to a
specific implementation.

They could have changed the size of long to 64-bits on their 64-bit
systems. Them and other companies. Now we will get long long, breaking
the real existing fundamental assumption/guarantee that long is the
largest signed integral built in type.

Completely irrational.
 
J

James Kanze

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

James Kanze

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

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 Question 9
size_t in C++ 0
size_t, ssize_t and ptrdiff_t 56
size_t in inttypes.h 4
The problem with size_t 45
size_t problems 466
64 bit C++ and OS defined types 71
size of bitfieds / strange warning 12

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top