64 bit C++ and OS defined types

C

Christopher

I am confused as I am converting my code to run on 64 bit. I know most
of the internals are specific to the compiler and implementation etc.

I can't decide whether how to handle standard types vs compiler
specific types.

I've thus far always opted to make a best effort to provide interfaces
that use standard types. However, I am now running into problems doing
that.

All my code that returned sizes is now returning 64 bit values, since
MS has made size_t 64 bits. My code used to treat these as 32 bit
unsigned integers. Heck, even the some of the Windows APIs expect 32
bit unsigned integers when passing parameters, but I get 64 bit
unsigned integers.

Anyway, is it bad practice for me to just give in and start using the
defined types MS provides instead of standard types? I am beginning to
believe it might make my job alot easier, even if my code is no longer
portable.

Also, should I start using 64 bit types whenever possible vs 32 bit
types, even if I don't think the values will grow that large? Does it
make a difference?

For instance I used to have a class something like this:

class MySpecialContainer
{
public:

const unsigned GetNumElements() const
{
return m_udts.size();
}

private:
unsigned m_numElements;

typedef std::vector<UDT> UDTVec;
UDTVec m_udts;
}


Now the return value of size() is 64 bits and does not convert to an
unsigned.
I could go and change everything to return size_t, but then I have to
change everywhere it is passed as a parameter, and half the APIs I
call are asking for a UINT, even the Windows APIs. I guess because
they expect the value to never grow that big. So, then I have to
static_cast<unsigned>( mySize_T) back again. I don't know what kind of
rules to adapt for these situations.
 
A

Alf P. Steinbach

* Christopher:
class MySpecialContainer
{
public:

const unsigned GetNumElements() const

The 'const' for the result type is superfluous and should be omitted.

The 'Get' in the name is superfluous and should be omitted (it may have some
purpose in Java but in C++ it's only noise, i.e. it has some negative impact for
readability etc. and adds nothing positive, so it's irrational to use it).

And even though the standard library has size methods with unsigned result type,
also that is an abomination. It's just sh*tty design, very much so, to use a C++
built-in type, where there's no guaranteed overflow checking, to indicate some
limited value range (technically: (1) it has no advantages, and (2) it has lots
of problems, including very serious ones, so (3) it's just sh*tty). Instead use
a signed type such as 'int' or 'long' or, if you absolutely must, 'ptrdiff_t'.

{
return m_udts.size();
}

private:
unsigned m_numElements;

typedef std::vector<UDT> UDTVec;
UDTVec m_udts;
}


Now the return value of size() is 64 bits and does not convert to an
unsigned.

It should convert.

If not then your compiler is very non-standard.

However, you should not use 'unsigned' here (see above).


Cheers & hth.,

- Alf
 
C

Christopher

* Christopher:

It should convert.

If not then your compiler is very non-standard.

However, you should not use 'unsigned' here (see above).

I am using VC 2008 SP1
Well, it does convert in the sense that I assign a 64 bit value to a
32 bit value with a compiler warning. However, I don't think having
9000 warnings is a good idea. I think the warning is legitimat too,
because who is to say I might not have a number of elements exceeding
the bounds of a 32 bit integer in the far off future?

I just don't know how to handle it. An int is 32 bits, a long is 32
bits, an unsigned int is 32 bits, but the size is 64 bits.
This is what I have to go on: http://msdn.microsoft.com/en-us/library/94z15h2c(VS.80).aspx

So, I am still unsure whether I should be using thier INT64 type
instead of the built in int type.
I am not even sure if __int64 is standard or also one of thier types.
 
A

Alf P. Steinbach

* Christopher:
I am using VC 2008 SP1
Well, it does convert in the sense that I assign a 64 bit value to a
32 bit value with a compiler warning. However, I don't think having
9000 warnings is a good idea.

That's where you use a static_cast.

I think the warning is legitimat too,
because who is to say I might not have a number of elements exceeding
the bounds of a 32 bit integer in the far off future?

You.

The trick is to balance guaranteed work now against marginally possible work in
the future sometime.

Consider that in the future, if that issue ever comes to the front, you might
just use LargeSize for 64 bit sizes. Or whatever. Done.

I just don't know how to handle it. An int is 32 bits, a long is 32
bits, an unsigned int is 32 bits, but the size is 64 bits.

In your original code you used 'unsigned', which is only guaranteed to have 16 bits.

So it's not a portability question.

It's only a question of what you design for in your current environment. Then
design for what's most practical.


I refuse to look up Microsoft documentation for a C++ issue.

So, I am still unsure whether I should be using thier INT64 type
instead of the built in int type.

No, you should not. Just the fact that it's all uppercase tells you that it was
designed by an incompetent (that is, Microsoft). Define your own signed Size type.

I am not even sure if __int64 is standard or also one of thier types.

It is a vendor defined type, as you can see from the double underscore.


Cheers & hth.,

- Alf
 
J

Juha Nieminen

Alf said:
The 'Get' in the name is superfluous and should be omitted (it may have
some purpose in Java but in C++ it's only noise, i.e. it has some
negative impact for readability etc. and adds nothing positive, so it's
irrational to use it).

I thought this newsgroup was about the C++ language, not about
programming guidelines. Suggesting to avoid using "get" in a getter
method is as superfluous here as suggesting eg. that one should use
reverse polish notation or how many spaces should be used for
indentation. It's a matter of style, not a matter of whether it's a
standard C++ feature.
And even though the standard library has size methods with unsigned
result type, also that is an abomination.

How do you suggest a program being able to use the entire address
space of the target architecture with a signed indexing type? Even if
you can address the entire address space with a signed type (as the CPU
will probably internally use the value as an unsigned type), you still
get problems when comparing indices with < when the indices go over the
half-way mark.

Or are you going to say "nobody will ever need more than half of the
address space of any computer architecture"?
 
A

Alf P. Steinbach

* Juha Nieminen:
I thought this newsgroup was about the C++ language, not about
programming guidelines.

It's about use of the C++ programming language. I'm always ready to revise my
judgement of what's topical or not. But, deciding on topicality every day for
clc++m, I think I have a pretty good grasp of that, thus, good arguments needed
to affect that judgment. ;-)

I have recently posted some other articles in this ng that were technically off
topic (although most of them of interest to the community).

But the above was not one of those OT articles, and it's just a silly argument.

Suggesting to avoid using "get" in a getter
method is as superfluous here as suggesting eg. that one should use
reverse polish notation or how many spaces should be used for
indentation. It's a matter of style, not a matter of whether it's a
standard C++ feature.

It is bad style in C++ precisely because C++ doesn't have any language feature
to make use of it (Java does have such a feature).

Reverse polish notation is also bad, but for another reason: C++ does have
language features that make that notation redundant and error prone, and since
it lowers readability and can easily become misleading, it's just dumb.

Both bad habits share the property of once having been meaningful and work
saving devices in some original environment (respectively Java for "Get" prefix
and Microsoft Programmers' Workbench for reverse polish notation) and then just
being silly muddifying stuff, causing extra work and lowering readability and
maintainability, when used in modern C++.

It's like handcranking the engine of your modern car instead of using starter key.

A frozen habit from ages ago, once meaningful, now the opposite.

How do you suggest a program being able to use the entire address
space of the target architecture with a signed indexing type? Even if
you can address the entire address space with a signed type (as the CPU
will probably internally use the value as an unsigned type), you still
get problems when comparing indices with < when the indices go over the
half-way mark.

That's a misunderstanding, sort of urban legend, unfortunately still bandied
about as if it were meaningful.

It isn't meaningful.

For in order to make use of the extra range of unsigned you need a /character/
(byte) array larger than one half of the address space. For 32-bit programs you
don't even have that address space available in Windows. For 64-bit programs,
when was the last time you needed a 2^63 bytes character array? And can you cite
any common computer with that much memory? I guess there might be a Cray...
Then, you're talking about /always/ using unsigned indexing in order to support
the case of using a Cray to address a larger than 2^63 character array. Hello.

Thus, when reduced to a concrete issue rather than hand waiving, it's not
meaningful at all, just technically bullshit. :)

It's best forgotten!

Or are you going to say "nobody will ever need more than half of the
address space of any computer architecture"?

That's a fallacy. Using signed indexing doesn't mean you can't use that much. It
means that if you need that much memory and can't reach it via indexing, then it
is necessarily for a character array that large. The OP's code will never be
used for a character array that large. Nor will my code or yours. I think. :)

Cheers & hth.,

- Alf
 
J

Juha Nieminen

Alf said:
For in order to make use of the extra range of unsigned you need a
/character/ (byte) array larger than one half of the address space.

So? You have never used byte arrays?
For
32-bit programs you don't even have that address space available in
Windows.

So C++ is now a Windows-exclusive programming language? Since when?

Besides, you are wrong: In 32-bit Windows the limit is 3 GB. (Granted,
you have to turn this feature on, as it's by default 2 GB, but it's
perfectly possible for programs to use up to 3 GB of memory. If you
don't know how, then maybe you should study the subject more.)
For 64-bit programs, when was the last time you needed a 2^63
bytes character array?

"640 kilobytes ought to be enough for anybody."

Aren't we already past these?
 
A

Alf P. Steinbach

* Juha Nieminen:
So? You have never used byte arrays?


So C++ is now a Windows-exclusive programming language? Since when?

Besides, you are wrong: In 32-bit Windows the limit is 3 GB. (Granted,
you have to turn this feature on, as it's by default 2 GB, but it's
perfectly possible for programs to use up to 3 GB of memory. If you
don't know how, then maybe you should study the subject more.)


"640 kilobytes ought to be enough for anybody."

Aren't we already past these?

Sorry, that's all grossly irrelevant.


Cheers, & hth.,

- Alf
 
B

Bart van Ingen Schenau

Anyway, is it bad practice for me to just give in and start using the
defined types MS provides instead of standard types? I am beginning to
believe it might make my job alot easier, even if my code is no longer
portable.

How would changing 'unsigned' to 'UINT' help you in the example below?
Most likely, 'UINT' is a typedef for 'unsigned int' anyway.
Also, should I start using 64 bit types whenever possible vs 32 bit
types, even if I don't think the values will grow that large? Does it
make a difference?

For instance I used to have a class something like this:

class MySpecialContainer
{
public:

   const unsigned GetNumElements() const
   {
      return m_udts.size();
   }

private:
   unsigned m_numElements;

   typedef std::vector<UDT> UDTVec;
   UDTVec m_udts;

}

Now the return value of size() is 64 bits and does not convert to an
unsigned.
I could go and change everything to return size_t, but then I have to
change everywhere it is passed as a parameter, and half the APIs I
call are asking for a UINT, even the Windows APIs. I guess because
they expect the value to never grow that big. So, then I have to
static_cast<unsigned>( mySize_T) back again. I don't know what kind of
rules to adapt for these situations.

You should look at the application logic.
If UINT_MAX has always been a few orders of magnitude larger than the
values returned from GetNumElements(), what makes you think that on a
64-bit platform your container will be storing so many more elements
that you actually need to count them in 64 bits?

If your problem is that the compiler has started to complain about the
conversion from size_t to unsigned, then you should use a cast in
GetNumElements itself (after you verified that 32-bit is indeed more
than enough). For added safety, you could add an 'assert(my_udts.size
() < UINT_MAX)'

Bart v Ingen Schenau
 
B

Bart van Ingen Schenau

* Christopher:





The 'const' for the result type is superfluous and should be omitted.

The 'Get' in the name is superfluous and should be omitted (it may have some
purpose in Java but in C++ it's only noise, i.e. it has some negative impact for
readability etc. and adds nothing positive, so it's irrational to use it)..

And what if the local coding rules state that "The name of a function
must start with an action verb", which is not an uncommon rule.
What verb do you propose to use instead of Get?
And even though the standard library has size methods with unsigned result type,
also that is an abomination. It's just sh*tty design, very much so, to use a C++
built-in type, where there's no guaranteed overflow checking, to indicate some
limited value range (technically: (1) it has no advantages, and (2) it has lots
of problems, including very serious ones, so (3) it's just sh*tty). Instead use
a signed type such as 'int' or 'long' or, if you absolutely must, 'ptrdiff_t'.

Do you have a document number for your formal proposal to deprecate
the unsigned types?
Cheers & hth.,

- Alf

Bart v Ingen Schenau
 
J

Juha Nieminen

Alf said:
Sorry, that's all grossly irrelevant.

Of course. Anything that makes your point weaker is "grossly
irrelevant". Anything that supports your point is, however, relevant.

I understand now.
 
A

Alf P. Steinbach

* Juha Nieminen:
Of course. Anything that makes your point weaker is "grossly
irrelevant". Anything that supports your point is, however, relevant.

I'm sorry, that just innuendo.

I understand now.

It seems you don't.

To have any argument at all there must be some connection with the issue
discussed. Hand-waiving doesn't cut it. It must be concrete.


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Bart van Ingen Schenau:
And what if the local coding rules state that "The name of a function
must start with an action verb", which is not an uncommon rule.
What verb do you propose to use instead of Get?

Just take it in stride and comply with the coding guidelines.

It's easy.

A coding guideline including a rule that adds needless work instead of saving
work just means you're working in a less than perfect environment. But nothing's
perfect. The question is whether the totality of rules is such that frustration
level is more than you can tolerate (at least for some persons there is a limit
to how much idiocy one can abide with) -- but that's a personal decision.

Do you have a document number for your formal proposal to deprecate
the unsigned types?

It's not a practical proposition to change the language or standard library in
that regard, nor is your particular proposed solution one that anyone competent
would want (unsigned types do have their uses, especially for bitlevel
manipulation). So I'm sorry but that question contains an invalid assumption of
the "have you stopped beating your wife" sort. It's purely silly-rhetorical.


Cheers & hth.,

- Alf
 
G

Goran

standard library has size methods with unsigned result type

.... and standard people are right and you are wrong ;-).

Name advantages and problems. You didn't do it, you just showed that
you gain nothing by using unsigned. That's neither advantage nor a
problem, and that was your only argument.

Here, some advantages of unsigned:

1. size is a __count__. Conceptually, it's a natural number. Same for
indexing. There's no element at position -1. Again, conceptually, it's
a natural number. The data type used (unsigned) reflects that. (IMHO,
this reason alone removes any need for a discussion).

2. in practice, an underflow with unsigned on raw arrays and some
(past?) implementations of STL leads to an earlier crash than going in
with e.g. -1.


Goran.
 
A

Alf P. Steinbach

* Goran:
... and standard people are right and you are wrong ;-).

Name advantages and problems. You didn't do it, you just showed that
you gain nothing by using unsigned. That's neither advantage nor a
problem, and that was your only argument.

Here, some advantages of unsigned:

1. size is a __count__. Conceptually, it's a natural number. Same for
indexing. There's no element at position -1. Again, conceptually, it's
a natural number. The data type used (unsigned) reflects that. (IMHO,
this reason alone removes any need for a discussion).

It is a Very Bad Idea to choose a C++ unsigned type to indicate numerical range,
because it doesn't enforce it. In Pascal, yes, there is a benefit; in Ada, yes,
there is a benefit; in C++, no, there is no benefit. On the contrary, in C++, by
doing that, you get all the problems and no benefits, hence it's plain stupid.

And I write that in spite of having mindlessly done the stupid thing for many
years (coming from Pascal/Modula-2, and seeing some experts doing the same in
C++), and having argued vociferously for it also in this group.

But it's never to late to learn, and when you start thinking about why the heck
you need an additional /hint/ that a size is non-negative, isn't "size" hint
enough, how dumb can a programmer be, really?, you realize that there's
something really fishy. Then thinking about actual benefits you find none, only
hand-waiving. Then thinking about problems and you find an abundance.

2. in practice, an underflow with unsigned on raw arrays and some
(past?) implementations of STL leads to an earlier crash than going in
with e.g. -1.

This is pretty unclear, but unsigned opens the door for more bugs, so this
argument about probability of detecting those bugs is pretty lame. :)

The problems with unsigned types are well known.

Your compiler, if it's any good, will warn you about comparisions
unsigned/signed. Those warnings are serious. Where you have such type mismatch
(which results from unsigned) you often have a bug. For example, if size is
unsigned and n is negative signed of small absolute value (which is typical),
then 'size < n' will often yield true because n is promoted to unsigned.

Your compiler cannot, however, warn you about arithmetic problems.

There's a host of bug vectors in that, including the main example of loop
counting down (incorrectly expressed).

One main problem is that you have to add casts and/or unnaturally choose types
and/or unnaturally express loops to avoid warnings and/or bugs (like infinite
loops) where you just know that those values are all non-negative. There would
have been no such problems with signed size types. So there's a lot of work
added just to avoid the problems one wouldn't have with signed sizes.

And a natural solution to that is to define one's own signed Size type.

And then define some generic function like

template< typename T > Size size( T const& );

Along with generic 'begin' and 'end' (that also work for raw arrays), and so on.

Hip hurray, all that **** removed.

Oh well, OK, not all, not by far. For such solutions cannot easily be
retrofitted onto existing code. But I argue for adopting the more sane way of
doing things for new code, including maintainance of old. :)


Cheers, & hth.,

- Alf
 
S

SaticCaster

The code analyzer Viva64 will simplify migration process!
http://www.viva64.com/viva64-tool/

Viva64 is a static code analyzer which was made to simplify porting
programs to 64-bit systems, and by means of that to reduce necessary
expenses. Viva64 works with C and C++ program code intended for 64-bit
Windows operation system. Viva64 is a connecting unit which integrates
into Visual Studio 2005/2008 development environment.
Using Viva64 static code analyzer allows to release a 64-bit
application 3 or 4 times faster. These results are reached because the
process of code analysis and testing is sped up considerably. This
requires taking into consideration specific character of 64-bit
architecture. The time devoted to testing of a developed 64-bit
software product is shortened owing to its higher quality. The
methodology of static code analysis used in Viva64 has some essential
advantages in comparison with other sorts of analysis because it
allows covering the whole program code. The procedure of code
verification cannot somehow damage the code itself. The process of
analysis is entirely controlled by a person and exactly the person
decides whether to modify it. Viva64 possesses a large knowledge base
concerning 64-bit code development (help system, articles, examples),
which will give a boost to the developers. If they follow the
recommendations given in these documents, both quality of code and its
productivity will be raised.

Viva64: What Is It, and Who Is It for?
http://www.viva64.com/art-1-2-903037923.html

64 bits, Wp64, Visual Studio 2008, Viva64 and all the rest...
http://www.viva64.com/art-1-2-621693540.html

20 issues of porting C++ code on the 64-bit platform
http://www.viva64.com/art-1-2-599168895.html
 
L

liam

Forgive me as I have not read all of the replies, yet I would use the
following with uses the same method as the standard.
class MySpecialContainer
{
public:
typedef std::vector<UDT> UDTVec
typedef UDTVec::size_type size_type;
size_type GetNumElements() const
{
return m_udts.size();
}

private:
/*I do not know the reason for the following but anyway*/
size_type m_numElements;
UDTVec m_udts;

}
 
J

Jorgen Grahn

* Juha Nieminen:

It's about use of the C++ programming language.

Yes. If we cannot talk about such things here, where should we do it?
I am here to become a better C++ programmer and having more fun while
doing it, by hearing what other people do, what they don't do, what
they like and so on.

Put differently, to me the culture and conventions *around* C++ is on
topic here. Not just the things you can quote from the standard.

That's also largely how this group works in practice. But sometimes
people play the "offtopic" card a bit too often, refuse to hypothesize
around things not covered by the standard, and so on.

/Jorgen
 
J

Jorgen Grahn

So, I am still unsure whether I should be using thier INT64 type
instead of the built in int type.
I am not even sure if __int64 is standard or also one of thier types.

I wouldn't use a type with a fixed size for no reason, and I hope the
Windows APIs do not have them in their signatures except where really
needed.

Your problem code upthread started with the size of a std::vector,
which is std::vector::size_type. Call me sloppy, but I'd handle it as
a size_t. I have no reason to claim to know that this type is 64 bits
(it isn't on half of my targets). Windows shouldn't have to know,
either.

I also wonder if you're not exaggerating the problem. Why would you
pass the size of a std::vector (or an index into a vector) into a
Windows API? I can't see that this would be very common.

/Jorgen
 

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


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top