By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,361 Members | 1,677 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,361 IT Pros & Developers. It's quick & easy.

static_cast<unsigned short)( -1 ) Well defined?

P: n/a
Is the following well defined?

size_t IntVal = 65537;
unsigned short Length;

if ( IntVal static_cast<unsigned short>( -1 ) )
{
std::cout << "Value too long to fit in a short" << std::endl;
}
else
{
std::cout << "Value fits" << std::endl;
Length = static_cast<unsigned short>( IntVal );
}

What I'm actually going to be using it for is to send a length short through
sockets, and I want to ensure that the length isn't greater than 65535.
Rather than the magic number, I was thinking that static_cast<unsigned
short>( -1 ) would be better. Is this well defined? Will it equal 65535 in
all cases where a short is a 2 byte integer?
Nov 21 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Jim Langston wrote:
Is the following well defined?

size_t IntVal = 65537;
unsigned short Length;

if ( IntVal static_cast<unsigned short>( -1 ) )
{
std::cout << "Value too long to fit in a short" << std::endl;
}
else
{
std::cout << "Value fits" << std::endl;
Length = static_cast<unsigned short>( IntVal );
}

What I'm actually going to be using it for is to send a length short
through sockets, and I want to ensure that the length isn't greater than
65535.
If that is want you want to check, you should say so:

if ( IntVal 65535 ) { ...

Rather than the magic number, I was thinking that
static_cast<unsigned short>( -1 ) would be better.
Why? If you want to check 65535, then presumably, your specs contain a
magic number. Your code should reflect that.
Is this well defined?
Your code has implementation defined behavior. Moreover, it is guaranteed,
that for IntVal <= 65535, the "Value fits" branch will be taken.
Will it equal 65535 in all cases where a short is a 2 byte integer?
Yes, provided your bytes have eight bits. However, your bytes maybe longer
and your shorts may have more than 2 bytes.
Now, you need to distinguish whether you want to check

(a) whether IntVal <= 65536, or
(b) whether IntVal can be faithfully represented as a short unsigned.

Your code does the later, and as far as I can see, it does so correctly.
Best

Kai-Uwe Bux
Nov 21 '06 #2

P: n/a

Jim Langston wrote:
Is the following well defined?

size_t IntVal = 65537;
unsigned short Length;

if ( IntVal static_cast<unsigned short>( -1 ) )
{
std::cout << "Value too long to fit in a short" << std::endl;
}
else
{
std::cout << "Value fits" << std::endl;
Length = static_cast<unsigned short>( IntVal );
}

What I'm actually going to be using it for is to send a length short through
sockets, and I want to ensure that the length isn't greater than 65535.
Rather than the magic number, I was thinking that static_cast<unsigned
short>( -1 ) would be better. Is this well defined? Will it equal 65535 in
all cases where a short is a 2 byte integer?
I doubt that can be enforced or guarenteed other than by checking
dutifully- but i may be wrong.
take a look at:
template<>
struct numeric_limits<unsigned short>
in...
#include <limits>

namespace Project {
typedef unsigned short usocket;
};

int main()
{
using Project::usocket;
using std::numeric_limits;
std::cout << "numeric_limits< usocket >::min() ";
std::cout << numeric_limits< usocket >::min();
std::cout << std::endl;
std::cout << "numeric_limits< usocket >::max() ";
std::cout << numeric_limits< usocket >::max();
std::cout << std::endl;

int n(65530);
for(size_t t = 0; t < 10; ++t)
{
std::cout << "n++ = " << n++;
usocket usock(static_cast<usocket>(n));
std::cout << "\tusock = " << usock;
std::cout << std::endl;
}
}

/*
numeric_limits< usocket >::min() 0
numeric_limits< usocket >::max() 65535
n++ = 65530 usock = 65531
n++ = 65531 usock = 65532
n++ = 65532 usock = 65533
n++ = 65533 usock = 65534
n++ = 65534 usock = 65535
n++ = 65535 usock = 0
n++ = 65536 usock = 1
n++ = 65537 usock = 2
n++ = 65538 usock = 3
n++ = 65539 usock = 4
*/

Nov 21 '06 #3

P: n/a
Jim Langston:
Is the following well defined?

size_t IntVal = 65537;

Slight problem here.

The range guaranteed for size_t is:

0 through 65535

On a system which has:

unsigned int : 16-Bit
unsigned long : 32-Bit
size_t : 16-Bit

, then this definition would be interpreted as:

size_t IntVal = 65537LU;

When converting to "size_t" the overflow would wrap around, making the
definition equivalent to:

size_t IntVal = 2;

unsigned short Length;

if ( IntVal static_cast<unsigned short>( -1 ) )

If you convert -1 to a unsigned integer type, then you're left with the
maximum value for that unsigned integer type. E.g.

char unsigned i = -1; char unsigned i = UCHAR_MAX;

short unsigned i = -1; short unsigned i = USHRT_MAX;

and so on...

Before the comparison takes place, the unsigned short value will be either
promoted to "int" or "unsigned int". Next, the types of the two operands will
be matched, possible yielding something like:

if ( (long unsigned)IntVal (long unsigned)USHRT_MAX )

{
std::cout << "Value too long to fit in a short" << std::endl;
}
else
{
std::cout << "Value fits" << std::endl;
Length = static_cast<unsigned short>( IntVal );
}

What I'm actually going to be using it for is to send a length short
through sockets, and I want to ensure that the length isn't greater than
65535. Rather than the magic number, I was thinking that
static_cast<unsigned short>( -1 ) would be better. Is this well
defined? Will it equal 65535 in all cases where a short is a 2 byte
integer?

To be honest, I'd have to read through the code in detail to see exactly what
you're trying to do... things to watch out for though are:

(1) Integer promotion (specifically, the possibility of "unsigned short"
promoting to "unsigned int" rather than "signed int").
(2) The range of "size_t" -- I'm not sure, but I think you could conceivably
have a system where:

typedef char unsigned size_t;

Of course, on such a system, a byte would have to be at least 16-Bit, but I
think you might want to watch out for:

sizeof(short unsigned) sizeof(size_t)

Of course, sizeof doesn't tell us how many value representation bits an
integer type has. To determine this, we can use the C-Style macro entitled
"IMAX_BITS" (Google for it), or we can use numeric_limits.

--

Frederick Gotham
Nov 21 '06 #4

P: n/a

"Frederick Gotham" <fg*******@SPAM.comwrote in message
news:dO*******************@news.indigo.ie...
Jim Langston:
>Is the following well defined?

size_t IntVal = 65537;


Slight problem here.

The range guaranteed for size_t is:

0 through 65535

On a system which has:

unsigned int : 16-Bit
unsigned long : 32-Bit
size_t : 16-Bit

, then this definition would be interpreted as:

size_t IntVal = 65537LU;
On my compiler size_t is defined thusly:

#ifndef _SIZE_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 size_t;
#else
typedef _W64 unsigned int size_t;
#endif
#define _SIZE_T_DEFINED
#endif

Basically an int. I'm not sure how it's defined on the 64 bit platform
(things that suggest they would go to 64 bit with the _W64 didnt'
necessarily).
>
When converting to "size_t" the overflow would wrap around, making the
definition equivalent to:

size_t IntVal = 2;

> unsigned short Length;

if ( IntVal static_cast<unsigned short>( -1 ) )


If you convert -1 to a unsigned integer type, then you're left with the
maximum value for that unsigned integer type. E.g.

char unsigned i = -1; char unsigned i = UCHAR_MAX;

short unsigned i = -1; short unsigned i = USHRT_MAX;

and so on...

Before the comparison takes place, the unsigned short value will be either
promoted to "int" or "unsigned int". Next, the types of the two operands
will
be matched, possible yielding something like:

if ( (long unsigned)IntVal (long unsigned)USHRT_MAX )

> {
std::cout << "Value too long to fit in a short" << std::endl;
}
else
{
std::cout << "Value fits" << std::endl;
Length = static_cast<unsigned short>( IntVal );
}

What I'm actually going to be using it for is to send a length short
through sockets, and I want to ensure that the length isn't greater than
65535. Rather than the magic number, I was thinking that
static_cast<unsigned short>( -1 ) would be better. Is this well
defined? Will it equal 65535 in all cases where a short is a 2 byte
integer?


To be honest, I'd have to read through the code in detail to see exactly
what
you're trying to do... things to watch out for though are:

(1) Integer promotion (specifically, the possibility of "unsigned short"
promoting to "unsigned int" rather than "signed int").
(2) The range of "size_t" -- I'm not sure, but I think you could
conceivably
have a system where:

typedef char unsigned size_t;

Of course, on such a system, a byte would have to be at least 16-Bit, but
I
think you might want to watch out for:

sizeof(short unsigned) sizeof(size_t)

Of course, sizeof doesn't tell us how many value representation bits an
integer type has. To determine this, we can use the C-Style macro entitled
"IMAX_BITS" (Google for it), or we can use numeric_limits.

--

Frederick Gotham

Nov 21 '06 #5

P: n/a
Jim Langston:
On my compiler size_t is defined thusly:

#ifndef _SIZE_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 size_t;
#else
typedef _W64 unsigned int size_t;
#endif
#define _SIZE_T_DEFINED
#endif

Basically an int. I'm not sure how it's defined on the 64 bit platform
(things that suggest they would go to 64 bit with the _W64 didnt'
necessarily).

I've no doubt that the code might work on your platform, or even on the
majority of platforms. And I've not doubt that your compiler documentation
might even define the behaviour of the code.

All I can tell you is that the behaviour of the snippet is not defined by the
C++ Standard.

--

Frederick Gotham
Nov 21 '06 #6

P: n/a
On Tue, 21 Nov 2006 14:11:21 GMT, Frederick Gotham
<fg*******@SPAM.comwrote in comp.lang.c++:
Jim Langston:
Is the following well defined?

size_t IntVal = 65537;


Slight problem here.

The range guaranteed for size_t is:

0 through 65535

On a system which has:

unsigned int : 16-Bit
unsigned long : 32-Bit
size_t : 16-Bit

, then this definition would be interpreted as:

size_t IntVal = 65537LU;
No, you're quite incorrect. Check the C++ standard. An unsuffixed
decimal literal never has an unsigned type. On a platform where int
has 16 bits:

size_t IntVal = 65537;

....is exactly equivalent to:

size_t IntVal = 65537L;

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 21 '06 #7

P: n/a
Frederick Gotham wrote:
Jim Langston:
>On my compiler size_t is defined thusly:

#ifndef _SIZE_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 size_t;
#else
typedef _W64 unsigned int size_t;
#endif
#define _SIZE_T_DEFINED
#endif

Basically an int. I'm not sure how it's defined on the 64 bit
platform (things that suggest they would go to 64 bit with the
_W64 didnt' necessarily).


I've no doubt that the code might work on your platform, or even on
the majority of platforms. And I've not doubt that your compiler
documentation might even define the behaviour of the code.
It does, even in 64 bit mode.
>
All I can tell you is that the behaviour of the snippet is not
defined by the C++ Standard.
We don't know that, unless we have checked all other defines used by the
particular implementation. With the right options set, _W64 is #define'd to
nothing. Then, if __int64 is #define'd as long, and long is big enough, it
could be correct.
Bo Persson
Nov 21 '06 #8

P: n/a
Bo Persson:
>I've no doubt that the code might work on your platform, or even on
the majority of platforms. And I've not doubt that your compiler
documentation might even define the behaviour of the code.

It does, even in 64 bit mode.

This is comp.lang.c++. Here's a list of newsgroups that this newsgroup is
not:

comp.lang.c++.mswindows.64
comp.lang.c++.playstation2
comp.lang.c++.whatever.implementation.you.can.find

I couldn't care less whether this code works on your interterrestial
spaceship, all I'm saying is that its behaviour is not defined by the C++
Standard. Here's another example of code I don't care about:

int main()
{
int i = 65535;

++i;
}

Will this program crash? That depends on the implementation. In the context
of portable code, the behaviour is undefined.

If you want to write platform-specific code which makes presumptions which
aren't necessitated by the Standard, then find another newsgroup.

>All I can tell you is that the behaviour of the snippet is not
defined by the C++ Standard.

We don't know that, unless we have checked all other defines used by the
particular implementation.

We know that it's not portable.

With the right options set, _W64 is #define'd
to nothing. Then, if __int64 is #define'd as long, and long is big
enough, it could be correct.

The behaviour of the code is implementation defined. Not only that though,
the implementation is free to leave the behaviour as undefined (e.g. in the
case of signed integer overflow).

--

Frederick Gotham
Nov 21 '06 #9

P: n/a
Frederick Gotham wrote:
Bo Persson:
>>I've no doubt that the code might work on your platform, or even
on the majority of platforms. And I've not doubt that your
compiler documentation might even define the behaviour of the
code.

It does, even in 64 bit mode.


This is comp.lang.c++. Here's a list of newsgroups that this
newsgroup is not:

comp.lang.c++.mswindows.64
comp.lang.c++.playstation2
comp.lang.c++.whatever.implementation.you.can.find

I couldn't care less whether this code works on your interterrestial
spaceship, all I'm saying is that its behaviour is not defined by
the C++ Standard. Here's another example of code I don't care about:

int main()
{
int i = 65535;

++i;
}

Will this program crash? That depends on the implementation. In the
context of portable code, the behaviour is undefined.

If you want to write platform-specific code which makes
presumptions which aren't necessitated by the Standard, then find
another newsgroup.
I hang around in other newsgroups too. Just thought you wanted it confirmed
that you were right.
>
>>All I can tell you is that the behaviour of the snippet is not
defined by the C++ Standard.

We don't know that, unless we have checked all other defines used
by the particular implementation.


We know that it's not portable.
It wasn't supposed to be portable, it is a part of one specific standard
library implementation. Whether it actually is standard conformant must be
on-topic here.
>
>With the right options set, _W64 is #define'd
to nothing. Then, if __int64 is #define'd as long, and long is big
enough, it could be correct.


The behaviour of the code is implementation defined. Not only that
though, the implementation is free to leave the behaviour as
undefined (e.g. in the case of signed integer overflow).
We can't tell just from the snippet whether it is conformant or not. It
depends on the definitions of the names _W64 and __int64, reserved to the
implementation. With the proper definitions, it just could be.
Bo Persson


Nov 22 '06 #10

P: n/a
Bo Persson:
We can't tell just from the snippet whether it is conformant or not. It
depends on the definitions of the names _W64 and __int64, reserved to
the implementation. With the proper definitions, it just could be.

It's implementation-defined as to whether the behaviour of the code is
undefined.

If you're interested, I started a thread over on comp.lang.c:

http://groups.google.ie/group/comp.l...f2bcf2bb366de4
4e/2156215b21253042?lnk=st&q=&rnum=1&hl=en#2156215b21 253042

(I posted on comp.lang.c rather than comp.lang.c++ as one tends to get better
answers to these kinds of questions there.)

--

Frederick Gotham
Nov 22 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.