Discussion:
Question about INT_PTR and int
(too old to reply)
Mikel
2008-11-03 10:00:18 UTC
Permalink
Hi,
I have a little question regarding INT_PTR and int.
I want to show the contents of a CArray in a CListCtrl so I've done
something like:

for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
c_List.InsertItem(i, [...]);
[...]
}

The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.

I know I could get rid of the warning by either changing the index
from INT_PTR to int or by doing an explicit cast, but both "solutions"
have their problems.

If I change the index type and at some point INT_PTR is bigger than
int, I could get and infinite loop (well, actually, the index would
wrap and become <0, so when accessing the array I would get an assert
or something).

And if I do an explicit cast, I would be in the same situation as I am
now, but without warnings.

Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents. But anyway, I would like to know how to deal
with this kind of "type-mismatch". Any ideas?

Thanks
Mikel
Giovanni Dicanio
2008-11-03 10:37:40 UTC
Permalink
Post by Mikel
for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
c_List.InsertItem(i, [...]);
[...]
}
The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.
I would write the loop using 'int', because CListCtrl::InsertItem() requires
a an int for the item index.
Post by Mikel
Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents.
So, just do:

int count = static_cast< int >( myArray.GetCount() );
for ( int i = 0; i < count; i++ )
{
c_List.InsertItem(i, ... );
...
}

A similar problem occurs with STL containers, that tend to use a size_t to
represent size, and size_t is defined as 'unsigned int', so in case you use
e.g. std::vector instead of CArray in the loop, there is a type mismatch in
the loop index (int) and array size (size_t).
As you kind of already wrote, considering that an int can store a maximum
positive value of 2^31-1 (on 32 bit) = 2,147,483,647, I consider that value
in lots of cases as a good reasonable maximum value.

However, for very robust code, you may consider a debug assertion (or
throwing a C++ STL exception) before the cast (at least for a size_t based
container):

ASSERT( myVector.size() <= 2147483647 );
int count = static_cast< int >( myVector.size() );
for ( int i = 0; i < count; i++ )
{
c_List.InsertItem( i, ... );
}

Or you may define a safe conversion function:

<code>

inline int size2int( size_t s )
{
// Make sure the cast from size_t to int is safe
const int maxValue = 2^31 - 1;
ASSERT( s <= maxValue ); // or throw...

return static_cast< int >( s );
}

</code>

and just use that.

Giovanni
Sheng Jiang[MVP]
2008-11-03 12:40:01 UTC
Permalink
better to compare the size of size_t and the size of INT_PTR in the assert
Post by Giovanni Dicanio
Post by Mikel
for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
c_List.InsertItem(i, [...]);
[...]
}
The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.
I would write the loop using 'int', because CListCtrl::InsertItem()
requires a an int for the item index.
Post by Mikel
Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents.
int count = static_cast< int >( myArray.GetCount() );
for ( int i = 0; i < count; i++ )
{
c_List.InsertItem(i, ... );
...
}
A similar problem occurs with STL containers, that tend to use a size_t to
represent size, and size_t is defined as 'unsigned int', so in case you
use e.g. std::vector instead of CArray in the loop, there is a type
mismatch in the loop index (int) and array size (size_t).
As you kind of already wrote, considering that an int can store a maximum
positive value of 2^31-1 (on 32 bit) = 2,147,483,647, I consider that
value in lots of cases as a good reasonable maximum value.
However, for very robust code, you may consider a debug assertion (or
throwing a C++ STL exception) before the cast (at least for a size_t based
ASSERT( myVector.size() <= 2147483647 );
int count = static_cast< int >( myVector.size() );
for ( int i = 0; i < count; i++ )
{
c_List.InsertItem( i, ... );
}
<code>
inline int size2int( size_t s )
{
// Make sure the cast from size_t to int is safe
const int maxValue = 2^31 - 1;
ASSERT( s <= maxValue ); // or throw...
return static_cast< int >( s );
}
</code>
and just use that.
Giovanni
Leo Violette
2008-11-03 15:50:09 UTC
Permalink
Well, if you really want to be 64-bit safe, you could do something like:

int iArraySize = 0;
if (myArray.GetCount() > MAX_INT)
{
iArraySize = MAX_INT;
_ASSERTE(false && _T("Precision Warning: You are exceeding a 32-bit
value! Time to migrate your app to fully support 64-bit?"));
}
else
iArraySize = static_cast<int>(myArray.GetCount()); // I think there is
also an ::IntPtrToInt function.

for (int iRow = 0; iRow < iArraySize; i++)
{
c_List.InsertItem(iRow, [...]);
[...]
}

This way, you are only casting when it's safe. The ASSERT really can only
happen in a 64-bit build when you are truncating from an 64-bit value to a
32-bit value.
Post by Mikel
Hi,
I have a little question regarding INT_PTR and int.
I want to show the contents of a CArray in a CListCtrl so I've done
for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
c_List.InsertItem(i, [...]);
[...]
}
The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.
I know I could get rid of the warning by either changing the index
from INT_PTR to int or by doing an explicit cast, but both "solutions"
have their problems.
If I change the index type and at some point INT_PTR is bigger than
int, I could get and infinite loop (well, actually, the index would
wrap and become <0, so when accessing the array I would get an assert
or something).
And if I do an explicit cast, I would be in the same situation as I am
now, but without warnings.
Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents. But anyway, I would like to know how to deal
with this kind of "type-mismatch". Any ideas?
Thanks
Mikel
Joseph M. Newcomer
2008-11-03 16:10:15 UTC
Permalink
This is one of the fundamental defects in how Microsoft has done INT_PTR. They have
functions (like GetCount()) that return INT_PTR, and APIs that still want int. So you end
up having to cast at some point to get the values to pass the compiler type checking.

for(int i = 0; i < (int)myArray.GetCount(); i++)

would probably be best. Besides, if you have more that 4.2 billion items in your list
control, it's going to take tens of minutes to load it, so I would not be overly concerned
with the reality of the overflow. It remains a serious problem, however, in the general
case.
joe
Post by Mikel
Hi,
I have a little question regarding INT_PTR and int.
I want to show the contents of a CArray in a CListCtrl so I've done
for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
c_List.InsertItem(i, [...]);
[...]
}
The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.
I know I could get rid of the warning by either changing the index
from INT_PTR to int or by doing an explicit cast, but both "solutions"
have their problems.
If I change the index type and at some point INT_PTR is bigger than
int, I could get and infinite loop (well, actually, the index would
wrap and become <0, so when accessing the array I would get an assert
or something).
And if I do an explicit cast, I would be in the same situation as I am
now, but without warnings.
Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents. But anyway, I would like to know how to deal
with this kind of "type-mismatch". Any ideas?
Thanks
Mikel
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Mikel
2008-11-04 08:57:57 UTC
Permalink
This is one of the fundamental defects in how Microsoft has done INT_PTR.  They have
functions (like GetCount()) that return INT_PTR, and APIs that still want int.  So you end
up having to cast at some point to get the values to pass the compiler type checking.
for(int i = 0; i < (int)myArray.GetCount(); i++)
would probably be best.  Besides, if you have more that 4.2 billion items in your list
control, it's going to take tens of minutes to load it, so I would not be overly concerned
with the reality of the overflow.  It remains a serious problem, however, in the general
case.
                                joe
Post by Mikel
Hi,
I have a little question regarding INT_PTR and int.
I want to show the contents of a CArray in a CListCtrl so I've done
for (INT_PTR i = 0; i < myArray.GetCount(); i++)
{
   c_List.InsertItem(i, [...]);
  [...]
}
The problem is I get a warning C4244 in InsertItem, because InsertItem
takes an int, so I'm converting an INT_PTR to int.
I know I could get rid of the warning by either changing the index
from INT_PTR to int or by doing an explicit cast, but both "solutions"
have their problems.
If I change the index type and at some point INT_PTR is bigger than
int, I could get and infinite loop (well, actually, the index would
wrap and become <0, so when accessing the array I would get an assert
or something).
And if I do an explicit cast, I would be in the same situation as I am
now, but without warnings.
Actually, I'm quite sure myArray won't be as big as to really have a
problem with this, and if it were, a CListCtrl would not be a good way
to show its contents. But anyway, I would like to know how to deal
with this kind of "type-mismatch". Any ideas?
Thanks
Mikel
Joseph M. Newcomer [MVP]
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm- Ocultar texto de la cita -
- Mostrar texto de la cita -
Thanks all for your answers.
Of course, I'm not going to add 2^32 elements to a CListCtrl, it
doesn't make sense. But I wanted to know how to deal with these
situations, in case some time in the future I find a symilar one that
does make sense.
Thanks again

Continue reading on narkive:
Loading...