Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

question about new and delete operator

0 views
Skip to first unread message

LiDongning

unread,
Jul 3, 2009, 3:57:26 PM7/3/09
to
Hi,
I'm working on a class which allocate some memory to store an array
(pointed by a pointer p_data). In constructor I use new to do the
allocation, in destructer I use delete to free the memory. In one
member function I wan to do something with the data (say, sort). In
that case, inside that function, I plan to allocate a piece memory to
store the processed data (p_processed), then free the original memory
(p_data), and point the p_data to p_process. The code will be
something like attached below. My question is, can i do something like
in the last two lines of code? Will this cause a memory leak or any
harmful effect? Thanks very much!

template <class T>
class data
{
int datanum;
T* p_data;
public:
data(int, T*);
~data();
void process();
};

template <class T>
data<T>::data(int in_n, T* in_data):datanum(in_n)
{
T* p_data = new T[datanum];
for (int i=0; i<datanum; i++) {p_data[i]=in_data[i];}
}

template <class T>
data<T>::~data()
{
delete []p_data;
}

template <class T>
void data<T>::process()
{
T* p_processed= new T[datanum];
//do something, so p_processed will be filled with processed data
for (int i=1; i<datanum; i++) {p_processed[i]=p_data[i];}
//processing finished
delete []p_data; // can i
do this??
p_data = p_processed; // can i do
this??
}

Jonathan Lee

unread,
Jul 3, 2009, 4:17:27 PM7/3/09
to
HI LiDongning,

> void data<T>::process()
> {
>      T* p_processed= new T[datanum];
>      //do something, so p_processed will be filled with processed data
>      for (int i=1; i<datanum; i++) {p_processed[i]=p_data[i];}
>      //processing finished
>      delete []p_data;                                        // can i
> do this??
>      p_data = p_processed;                             // can i do
> this??
>
> }
>

That's fine. You've just exchanged the arrays. p_data will still
be a valid pointer for when the destructor is called.

But the way you've phrased it, why not just calculate the result
directly in p_data and then delete[] p_processed? It seems that they
are the same size and p_processed is initialized to be a copy
of p_data. I'm not sure what would stop you from making p_data
the destination for your processing. If you were really cautious
about the delete[], then that would be a solution.

--Jonathan

Yan

unread,
Jul 3, 2009, 4:36:04 PM7/3/09
to
On Jul 3, 3:57 pm, LiDongning <lidongn...@gmail.com> wrote:

>      T* p_processed= new T[datanum];
>      //do something, so p_processed will be filled with processed data
>      for (int i=1; i<datanum; i++) {p_processed[i]=p_data[i];}
>      //processing finished
>

it's seems all good. i would however, if i were you, make sure that
the 'processing' part doesn't throw, because if it does the memory
allocated for p_processed won't get freed.

Lars Tetzlaff

unread,
Jul 4, 2009, 7:27:56 AM7/4/09
to
LiDongning schrieb:

> Hi,
> I'm working on a class which allocate some memory to store an array
> (pointed by a pointer p_data). In constructor I use new to do the
> allocation, in destructer I use delete to free the memory. In one
> member function I wan to do something with the data (say, sort). In
> that case, inside that function, I plan to allocate a piece memory to
> store the processed data (p_processed), then free the original memory
> (p_data), and point the p_data to p_process. The code will be
> something like attached below. My question is, can i do something like
> in the last two lines of code? Will this cause a memory leak or any
> harmful effect? Thanks very much!
>

I would recommend to use std::vector like this:

#include <vector>

template <class T>
class data
{

std::vector<T> m_data;
public:
data(int, T*);
void process();
};

template <class T>
data<T>::data(int in_n, T* in_data)

: m_data( in_data, in_data + in_n )
{
}

template <class T>
void data<T>::process()
{

std::vector<T> processed( m_data.begin(), m_data.end() );
// do something with your copy

// assign processed data to m_data
m_data.swap( processed );
}


This code is shorter *and* exception safe.


Lars

LiDongning

unread,
Jul 4, 2009, 12:17:41 PM7/4/09
to

Jonathan,
Thanks for the reply. The reason I allocate a p_process array is that
I want to do a sorting for the data in the p_data array. If I use a
binary tree algorithm, the original data have to be kept until the
sorting is finished.
DOngning

LiDongning

unread,
Jul 4, 2009, 12:24:33 PM7/4/09
to
On Jul 4, 6:27 am, Lars Tetzlaff <lars.tetzl...@gmx.net> wrote:
> LiDongning schrieb:
>
> > Hi,
> > I'm working on a class which allocate some memory to store an array
> > (pointed by a pointer p_data). In constructor I use new to do the
> > allocation, in destructer I use delete to free the memory. In one
> > member function I wan to do something with the data (say, sort). In
> > that case, inside that function, I plan to allocate a piece memory to
> > store the processed data (p_processed), then free the original memory
> > (p_data), and point the p_data to p_process. The code will be
> > something like attached below. My question is, can i do something like
> > in the last two lines of code? Will this cause a memory leak or any
> > harmful effect? Thanks very much!
>
> I would recommend to use std::vector like this:
>
> #include <vector>
>
> template <class T>
> class data
> {
>   std::vector<T> m_data;
> public:
>   data(int, T*);
>   void process();
>
> };
>
> template <class T>
> data<T>::data(int in_n, T* in_data)
> : m_data( in_data, in_data + in_n )
> {
>
> }
>
Exactly! Thanks much!

Hendrik Schober

unread,
Jul 5, 2009, 4:39:53 PM7/5/09
to
Lars Tetzlaff wrote:
> LiDongning schrieb:
>> Hi,
>> I'm working on a class which allocate some memory to store an array
>> (pointed by a pointer p_data). In constructor I use new to do the
>> allocation, in destructer I use delete to free the memory. In one
>> member function I wan to do something with the data (say, sort). In
>> that case, inside that function, I plan to allocate a piece memory to
>> store the processed data (p_processed), then free the original memory
>> (p_data), and point the p_data to p_process. The code will be
>> something like attached below. My question is, can i do something like
>> in the last two lines of code? Will this cause a memory leak or any
>> harmful effect? Thanks very much!
>>
>
> I would recommend to use std::vector like this:
>
> #include <vector>
>
> template <class T>
> class data
> {
> std::vector<T> m_data;
> public:
> data(int, T*);
> void process();
> };
>
> template <class T>
> data<T>::data(int in_n, T* in_data)
> : m_data( in_data, in_data + in_n )
> {
> }

Why 'int'? Will there ever be a sequence of -5 bytes?

> [...]
> Lars

Schobi

Juha Nieminen

unread,
Jul 5, 2009, 5:09:27 PM7/5/09
to
Hendrik Schober wrote:
> Why 'int'? Will there ever be a sequence of -5 bytes?

In my experience using signed types even in situations where negative
values have no rational meaning lessens problems in the long run.

For example, assume you are making a class which represents an image.
The class will have two integral members denoting the pixel width and
height of the image. Since it doesn't make sense to have images with
negative width or height, the most logical thing to do would be to make
these two integrals unsigned, right?

Well, no. Let's assume that in the application where the class is used
the images are drawn on screen, eg. as sprites. The image may be drawn
partially outside of the screen. In other words, the coordinates where
the image is drawn may well be negative.

Now, if you need to perform any arithmetic using the coordinates and
the dimensions of the image (which is very usual in such situations),
you will have a clash between signed and unsigned types. In certain
situations you might end up with incorrect results (eg. if floating
point calculations are involved, something might end up at the
coordinate 4294967295 or whatever). I have had this problem in practice,
so it's not purely theoretical stuff.

Paavo Helde

unread,
Jul 6, 2009, 2:15:02 AM7/6/09
to
Hendrik Schober <spam...@gmx.de> kirjutas:
[...]

>> #include <vector>
>>
>> template <class T>
>> class data
>> {
>> std::vector<T> m_data;
>> public:
>> data(int, T*);
>> void process();
>> };
>>
>> template <class T>
>> data<T>::data(int in_n, T* in_data)
>> : m_data( in_data, in_data + in_n )
>> {
>> }
>
> Why 'int'? Will there ever be a sequence of -5 bytes?

We have had this discussion before in this group, several times. In C++,
the unsigned types are quite specific types with special rollover effects
and there are tricky promotion rules for mixed-signedness arithmetic
expressions. Unless unsignedness is strongly needed, I would avoid those
types.

In the above example, if in_n would happen to have value -5, this would
indicate a clear error and could be handled properly. If in_n was
unsigned, then all values would be valid, in particular wrapover at zero
would be well-defined and the compiler is even not allowed to insert
debug checks for detecting the wrapover.

Paavo


James Kanze

unread,
Jul 6, 2009, 5:58:40 AM7/6/09
to
On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> Lars Tetzlaff wrote:
> > LiDongning schrieb:

> >> I'm working on a class which allocate some memory to store

> > #include <vector>

Because int is the "standard" type for integral values in C++.
Anything else should only be used if int won't do the job; the
only justification for not using int here would be that there
might be sequences of more that INT_MAX bytes.

--
James Kanze (GABI Software) email:james...@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

Hendrik Schober

unread,
Jul 7, 2009, 5:01:57 AM7/7/09
to
Paavo Helde wrote:
> Hendrik Schober <spam...@gmx.de> kirjutas:
> [...]
>> Why 'int'? Will there ever be a sequence of -5 bytes?
>
> We have had this discussion before in this group, several times.

I'm sorry I missed this. I'm not a regular reader. I don't
have enough time to be. Feel free to ignore any discussion
stemming from this.

> In C++,
> the unsigned types are quite specific types with special rollover effects
> and there are tricky promotion rules for mixed-signedness arithmetic
> expressions. Unless unsignedness is strongly needed, I would avoid those
> types.

Well, call me strict, but I happen to believe that, for
specifying sizes, unsignedness is strongly needed. I also
believe that, if a positive value is needed in order to
call a function, the function's interface should say so.
Yes, I know, implicit promotion etc. can wreak havoc when
you have huge unsigned numbers. Still, if I have to decide
between having the right interface and maybe having to
find funny errors due to this, or having a wrong interface
and maybe having to find funny errors due to negative
values being past, I'd go for the right interface.

> In the above example, if in_n would happen to have value -5, this would
> indicate a clear error and could be handled properly. If in_n was
> unsigned, then all values would be valid, in particular wrapover at zero
> would be well-defined and the compiler is even not allowed to insert
> debug checks for detecting the wrapover.

<http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf>
<http://www.aristeia.com/Papers/C++ReportColumns/feb96.pdf>

> Paavo

Schobi

Hendrik Schober

unread,
Jul 7, 2009, 5:08:41 AM7/7/09
to
James Kanze wrote:
> On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>> Lars Tetzlaff wrote:
> [...]

>>> template <class T>
>>> data<T>::data(int in_n, T* in_data)
>>> : m_data( in_data, in_data + in_n )
>>> {
>>> }
>
>> Why 'int'? Will there ever be a sequence of -5 bytes?
>
> Because int is the "standard" type for integral values in C++.
> Anything else should only be used if int won't do the job; the
> only justification for not using int here would be that there
> might be sequences of more that INT_MAX bytes.

You state this as an axiom. Note that I asked "why".
Had I subscribed to the axiom, I wouldn't have asked.
(To cut a few corners in this discussion: I subscribe
to the axiom of always choosing the data type that is
the best representation of the data. If the data is
natural, positive numbers, an unsigned type seems to
be the natural fit for the job.)

Schobi

Hendrik Schober

unread,
Jul 7, 2009, 5:05:22 AM7/7/09
to
Juha Nieminen wrote:
> Hendrik Schober wrote:
>> Why 'int'? Will there ever be a sequence of -5 bytes?
>
> In my experience using signed types even in situations where negative
> values have no rational meaning lessens problems in the long run.
>
> For example, assume you are making a class which represents an image.
> The class will have two integral members denoting the pixel width and
> height of the image. Since it doesn't make sense to have images with
> negative width or height, the most logical thing to do would be to make
> these two integrals unsigned, right?
>
> Well, no. Let's assume that in the application where the class is used
> the images are drawn on screen, eg. as sprites. The image may be drawn
> partially outside of the screen. In other words, the coordinates where
> the image is drawn may well be negative.

Note that these are other coordinates than the image's.
<shrug> Between different coordinate systems, you will
have to convert. Easing this /might/ be a reason to
chose the "wrong" types for one of the systems -- but
that doesn't mean that this should be a general advice.

> [...]

Schobi

Alf P. Steinbach

unread,
Jul 7, 2009, 5:31:04 AM7/7/09
to
* Hendrik Schober:

> Paavo Helde wrote:
>> Hendrik Schober <spam...@gmx.de> kirjutas:
>> [...]
>>> Why 'int'? Will there ever be a sequence of -5 bytes?
>>
>> We have had this discussion before in this group, several times.
>
> I'm sorry I missed this. I'm not a regular reader. I don't
> have enough time to be. Feel free to ignore any discussion
> stemming from this.
>
>> In
>> C++, the unsigned types are quite specific types with special rollover
>> effects and there are tricky promotion rules for mixed-signedness
>> arithmetic expressions. Unless unsignedness is strongly needed, I
>> would avoid those types.
>
> Well, call me strict, but I happen to believe that, for
> specifying sizes, unsignedness is strongly needed. I also
> believe that, if a positive value is needed in order to
> call a function, the function's interface should say so.
> Yes, I know, implicit promotion etc. can wreak havoc when
> you have huge unsigned numbers.

Apparently you don't understand the problems.


> Still, if I have to decide
> between having the right interface and maybe having to
> find funny errors due to this, or having a wrong interface
> and maybe having to find funny errors due to negative
> values being past, I'd go for the right interface.

In C or C++, unsigned type is far more likely to yield "funny errors".

Choosing types in a good way is a matter of programming language.

Cheers & hth.,

- Alf

James Kanze

unread,
Jul 7, 2009, 7:43:31 AM7/7/09
to
On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> > On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> >> Lars Tetzlaff wrote:
> > [...]
> >>> template <class T>
> >>> data<T>::data(int in_n, T* in_data)
> >>> : m_data( in_data, in_data + in_n )
> >>> {
> >>> }

> >> Why 'int'? Will there ever be a sequence of -5 bytes?

> > Because int is the "standard" type for integral values in
> > C++. Anything else should only be used if int won't do the
> > job; the only justification for not using int here would be
> > that there might be sequences of more that INT_MAX bytes.

> You state this as an axiom.

Because it is an axiom. It's part of the original definition of
C.

> Note that I asked "why".

Because that's the way the language designers designed the
language. I'm not saying that it's right---I sort of liked
Modula-2's CARDINAL type. But C and C++ don't have one.

> Had I subscribed to the axiom, I wouldn't have asked.
> (To cut a few corners in this discussion: I subscribe
> to the axiom of always choosing the data type that is
> the best representation of the data. If the data is
> natural, positive numbers, an unsigned type seems to
> be the natural fit for the job.)

To be reasonable, you need to include behavior in the
representation. If the data is natural, positive numbers,
subtraction can still result in a negative value---when choosing
a type, either the type will allow a signed result in the case
of subtraction, or it won't support subtraction (case of
Modula-2). You also have to choose the type in the context of
the whole type system: in C++, if you use unsigned in an
expression with a signed, it changes the meaning of the signed
in strange ways.

In the end, a language is designed the way it is designed. You
can fight it, but you won't win. Kernighan and Richie decided
that the principal integral type in C would be int; all other
types have been added for specific needs, but int remains THE
integral type. Anytime you use anything else (for integral
values, of course), you're fighting the language: introducing
additional complexity and additional possibilities for errors.

Hendrik Schober

unread,
Jul 7, 2009, 10:05:09 AM7/7/09
to
James Kanze wrote:
> On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
>> James Kanze wrote:
>>> On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>>>> Lars Tetzlaff wrote:
>>> [...]
>>>>> template <class T>
>>>>> data<T>::data(int in_n, T* in_data)
>>>>> : m_data( in_data, in_data + in_n )
>>>>> {
>>>>> }
>
>>>> Why 'int'? Will there ever be a sequence of -5 bytes?
>
>>> Because int is the "standard" type for integral values in
>>> C++. Anything else should only be used if int won't do the
>>> job; the only justification for not using int here would be
>>> that there might be sequences of more that INT_MAX bytes.
>
>> You state this as an axiom.
>
> Because it is an axiom. It's part of the original definition of
> C.

Mhmm. I've never owned a C standard, so I only know
from hearsay, but so far I always assumed 'int' was
"the native integer type on the platform", meaning
that it is the one the platform is fastest with.

> [...]


> To be reasonable, you need to include behavior in the
> representation. If the data is natural, positive numbers,

> subtraction can still result in a negative value [...]

Yep. And when dividing with 'double', you have to be
careful, since a '0.0' might be fatal. What's the
fundamental different to subtracting unsigned integers?

> In the end, a language is designed the way it is designed. You
> can fight it, but you won't win. Kernighan and Richie decided
> that the principal integral type in C would be int; all other
> types have been added for specific needs, but int remains THE
> integral type. Anytime you use anything else (for integral
> values, of course), you're fighting the language: introducing
> additional complexity and additional possibilities for errors.

Mhmm. Then who added 'size_t' to be used for sizes
to this language?

Schobi

Bo Persson

unread,
Jul 7, 2009, 12:06:01 PM7/7/09
to
Hendrik Schober wrote:
> Paavo Helde wrote:
>> Hendrik Schober <spam...@gmx.de> kirjutas:
>> [...]
>>> Why 'int'? Will there ever be a sequence of -5 bytes?
>>
>> We have had this discussion before in this group, several times.
>
> I'm sorry I missed this. I'm not a regular reader. I don't
> have enough time to be. Feel free to ignore any discussion
> stemming from this.
>
>> In
>> C++, the unsigned types are quite specific types with special
>> rollover effects and there are tricky promotion rules for
>> mixed-signedness arithmetic expressions. Unless unsignedness is
>> strongly needed, I would avoid those types.
>
> Well, call me strict, but I happen to believe that, for
> specifying sizes, unsignedness is strongly needed. I also
> believe that, if a positive value is needed in order to
> call a function, the function's interface should say so.

But that doesn't save you from anyone passing a -5, as that will
"work" for an unsigned parameter as well.

Bo Persson


Hendrik Schober

unread,
Jul 7, 2009, 1:13:22 PM7/7/09
to

Of course, it doesn't. However, it does communicate
that -5 is not a valid value.

> Bo Persson

Schobi

Alf P. Steinbach

unread,
Jul 8, 2009, 2:10:56 AM7/8/09
to
* Hendrik Schober:

If you fail to communicate the function's contract to client programmers then
you have a problem. You seem to think that that communication problem can be
alleviated by using unsigned types in C or C++. Well that's backward: to anyone
competent you're just communicating that you don't know what you're about, so
that it would be wrong to expect *anything* to be reasonable, i.e., by using
unsigned type you actively engage in failing to do what you wanted, communicate.

And if the function fails to enforce its contract to the degree possible you
have a much more serious problem, because all experience shows that without
automated error detection it's practically impossible to avoid errors.

The client code programmer may have a 100% perfect understanding of your
function's contract, but still manage to call it with invalid arguments.

And what happens when you pass -5 to your unsigned formal argument?

The language standard then guarantees wrapping, that you get the value 2^n-5
where n is the number of value representation bits, and do you check for that?
No? I thought so.

Paavo Helde

unread,
Jul 8, 2009, 2:45:57 AM7/8/09
to
Hendrik Schober <spam...@gmx.de> kirjutas:

Did you read the articles yourself? The first one strictly disagrees with
using 'unsigned' and the second one reluctantly tries to find ways to use
'unsigned', only after receiving lots of angry emails from readers like
you (and probably after being called on the carpet by the editor-in-
chief...).

The point is that when you get experienced enough, you start to
understand the deficiencies of the language, and what is the best way to
use the language. I know I myself believed many years ago that using
'unsigned' is a good way to communicate the information that the
paramater may not be negative, and unfortunately I'm still stuck with the
interfaces I wrote that time, because of backward compatibility concerns.

Paavo

Hendrik Schober

unread,
Jul 8, 2009, 5:37:27 AM7/8/09
to
Alf P. Steinbach wrote:
> * Hendrik Schober:
>> Bo Persson wrote:
>>> Hendrik Schober wrote:
>>>> Paavo Helde wrote:
>>>>> Hendrik Schober <spam...@gmx.de> kirjutas:
>>>>> [...]
>>>>>> Why 'int'? Will there ever be a sequence of -5 bytes?
> [...]

>>>>> In
>>>>> C++, the unsigned types are quite specific types with special
>>>>> rollover effects and there are tricky promotion rules for
>>>>> mixed-signedness arithmetic expressions. Unless unsignedness is
>>>>> strongly needed, I would avoid those types.
>>>> Well, call me strict, but I happen to believe that, for
>>>> specifying sizes, unsignedness is strongly needed. I also
>>>> believe that, if a positive value is needed in order to
>>>> call a function, the function's interface should say so.
>>> But that doesn't save you from anyone passing a -5, as that will
>>> "work" for an unsigned parameter as well.
>> Of course, it doesn't. However, it does communicate
>> that -5 is not a valid value.
>
> If you fail to communicate the function's contract to client programmers then
> you have a problem.

Right. Which is why I put great emphasis on communicating
this. In the language, rather than in comments.

> You seem to think that that communication problem can be

> alleviated by using unsigned types in C or C++. [...]

And you seem to think that communication between callers
and callees has to happen solely through comments. (Just
as stupid an accusation, I know. Couldn't resist, though.)

If communication solely through comments was fine, all
functions should take and return only 'void*'. (Or they
might take an ellipsis. You can communicate the number
of arguments through comments, after all.) Since this not
only isn't done, but frowned upon, and since the language
even more and more develops towards the exact opposite
(expressing of constraints directly in the language,
instead of in comments), I conclude there's a general
consensus that this is better.

> [...]


> The client code programmer may have a 100% perfect understanding of your
> function's contract, but still manage to call it with invalid arguments.
>
> And what happens when you pass -5 to your unsigned formal argument?
>
> The language standard then guarantees wrapping, that you get the value 2^n-5
> where n is the number of value representation bits, and do you check for that?
> No? I thought so.

Does your implementation of
std::vector<T>::operator[](size_type)
check whether you pass -5 into it? No? I thought so.
And what happens if you do anyway? Right. I thought so,
too.
And if you manage to still get this wrong even though
you have a 100% perfect understanding of the fact that
the operator requires an unsigned? See. Again, I thought
so.

> - Alf

Schobi

James Kanze

unread,
Jul 8, 2009, 5:44:59 AM7/8/09
to
On Jul 7, 7:13 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> Bo Persson wrote:

[...]


> > But that doesn't save you from anyone passing a -5, as that will
> > "work" for an unsigned parameter as well.

> Of course, it doesn't. However, it does communicate that -5 is
> not a valid value.

Not really, since -5 is a perfectly legal value to use when
initializing an unsigned. But that's not really the point: the
unsigned integral types in C++ are fairly special, and using
unsigned communicates (to someone who knows C++, at least) that
you require some of its special qualities: modulo arithmetic, or
correct behavior for bitwise operators.

Hendrik Schober

unread,
Jul 8, 2009, 5:45:29 AM7/8/09
to
Alf P. Steinbach wrote:
> * Hendrik Schober:
>> Paavo Helde wrote:
>>> Hendrik Schober <spam...@gmx.de> kirjutas:
>>> [...]
>>>> Why 'int'? Will there ever be a sequence of -5 bytes?
>>> We have had this discussion before in this group, several times.
>>>
>> I'm sorry I missed this. I'm not a regular reader. I don't
>> have enough time to be. Feel free to ignore any discussion
>> stemming from this.
>
> [...]

>
> Apparently you don't understand the problems.

And apparently you don't feel like explaining them.
So why bother posting?

> [...]
> - Alf

Schobi

James Kanze

unread,
Jul 8, 2009, 6:01:50 AM7/8/09
to
On Jul 7, 4:05 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> > On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
> >> James Kanze wrote:
> >>> On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> >>>> Lars Tetzlaff wrote:
> >>> [...]
> >>>>> template <class T>
> >>>>> data<T>::data(int in_n, T* in_data)
> >>>>> : m_data( in_data, in_data + in_n )
> >>>>> {
> >>>>> }

> >>>> Why 'int'? Will there ever be a sequence of -5 bytes?

> >>> Because int is the "standard" type for integral values in
> >>> C++. Anything else should only be used if int won't do
> >>> the job; the only justification for not using int here
> >>> would be that there might be sequences of more that
> >>> INT_MAX bytes.

> >> You state this as an axiom.

> > Because it is an axiom. It's part of the original
> > definition of C.

> Mhmm. I've never owned a C standard, so I only know from
> hearsay, but so far I always assumed 'int' was "the native
> integer type on the platform",

And how is this different from "the standard type"?

> meaning that it is the one the platform is fastest with.

Speed doesn't necessarily have much to do with it. It's true
that on some platforms, anything involving unsigned is
significantly slower than signed, but on most platforms, it
makes absolutely no difference, and never had.

> > [...]
> > To be reasonable, you need to include behavior in the
> > representation. If the data is natural, positive numbers,
> > subtraction can still result in a negative value [...]

> Yep. And when dividing with 'double', you have to be
> careful, since a '0.0' might be fatal. What's the
> fundamental different to subtracting unsigned integers?

Because there's no relationship whatsoever between them. The
subtraction of two natural numbers is a well defined operation;
division by 0 isn't.

> > In the end, a language is designed the way it is designed. You
> > can fight it, but you won't win. Kernighan and Richie decided
> > that the principal integral type in C would be int; all other
> > types have been added for specific needs, but int remains THE
> > integral type. Anytime you use anything else (for integral
> > values, of course), you're fighting the language: introducing
> > additional complexity and additional possibilities for errors.

> Mhmm. Then who added 'size_t' to be used for sizes
> to this language?

I don't know. That came a lot later. (Don't forget, however,
that size_t was originally designed to represent something very
low level, which often wouldn't fit in an int.)

Hendrik Schober

unread,
Jul 8, 2009, 6:06:22 AM7/8/09
to
Paavo Helde wrote:
> Hendrik Schober <spam...@gmx.de> kirjutas:
> [...]
>

What do you think? That I googled them up and, since a few
keywords appeared in them, I just threw them at you?
<shakes head>
(In fact, I suspect it's hard to come up with a few keywords
for google to put them among the first ten hits.)

> The first one strictly disagrees with
> using 'unsigned' and the second one reluctantly tries to find ways to use
> 'unsigned', only after receiving lots of angry emails from readers like
> you (and probably after being called on the carpet by the editor-in-
> chief...).

<smiles>
Why don't you go and ask Scott about whether your fantasies
are true?

> The point is that when you get experienced enough, you start to
> understand the deficiencies of the language, and what is the best way to
> use the language. I know I myself believed many years ago that using
> 'unsigned' is a good way to communicate the information that the
> paramater may not be negative, and unfortunately I'm still stuck with the
> interfaces I wrote that time, because of backward compatibility concerns.

Like in the std lib, right?

> Paavo

Schobi

Paavo Helde

unread,
Jul 8, 2009, 1:50:29 PM7/8/09
to
Hendrik Schober <spam...@gmx.de> kirjutas:

Yes, the use of size_t and its friends in STL also causes some headaches.

Well, I try to bring you an example. I do not hope though you will be
affected by this until you get bitten yourself. But I do my best.

Say, you have to force a rectangle into a bounding box (so that no parts
of rectangle lie outside of bounding box). For clarity I will only use x
coordinate here. Coordinates may become negative, the boxes' widths
naturally not, so they are encoded as unsigned, according to the
proponents of the 'unsigned' party. Let's say you have interfaces:

void GetRectangle(int& left, unsigned int& width);
void GetBoundingBox(int& left, unsigned int& width);
void SetRectangle(int& left, unsigned int& width);

First implementation might be something like that:

int rc_left, bbox_left;
unsigned int rc_width, bbox_width;

GetRectangle(rc_left, rc_width);
GetBoundingBox(bbox_left, bbox_width);

if (rc_left<bbox_left) {
rc_left=bbox_left;
}
if (rc_left+rc_width>bbox_left+bbox_width) {
rc_width = bbox_left+bbox_width-rc_left;
}
SetRectangle(rc_left, rc_width);

Everything seems to work initially, no warnings from compiler. However,
when used with inital data

rc_left=-500
rc_width=200
bbox_left=-100;
bbox_width=50;

the end results for the rectangle will be -100 and 200. How comes? A
rectangle of width 200 would never fit into a bounding box of width 50!

When you have had a similar bug in your code, and wasted lots of time
finding and understanding it, then you would start to understand why the
unsigned types are not so harmless in C++. The best way to treat them is
to cast them to signed types immediately, but why then bother to have
them unsigned in the first place?

Best regards
Paavo

Paavo Helde

unread,
Jul 8, 2009, 3:48:21 PM7/8/09
to
Paavo Helde <pa...@nospam.please.ee> kirjutas:

Make the above three lines just

rc_left=bbox_left;

to make the algorithm better defined and more to the point.

io_x

unread,
Jul 9, 2009, 2:57:20 AM7/9/09
to
+comp.lang.c
"James Kanze" <james...@gmail.com> ha scritto nel messaggio
news:5dd8555d-02fd-4db2...@l31g2000yqb.googlegroups.com...

>In the end, a language is designed the way it is designed. You
>can fight it, but you won't win. Kernighan and Richie decided
>that the principal integral type in C would be int; all other
>types have been added for specific needs, but int remains THE
>integral type.

the "unsigned int" is the easier type if it is easy
there is more chance to go all right in the code

if i have to save something, the first types data i save wuould be
u8, u32, u64, ... unsigned types

the main type, is not "int" it is "unsigned int"

Nick Keighley

unread,
Jul 9, 2009, 4:07:46 AM7/9/09
to
On 8 July, 10:37, Hendrik Schober <spamt...@gmx.de> wrote:
> Alf P. Steinbach wrote:
> > * Hendrik Schober:
> >> Bo Persson wrote:
> >>> Hendrik Schober wrote:
> >>>> Paavo Helde wrote:

<snip>

> >>>>> In
> >>>>> C++, the unsigned types are quite specific types with special
> >>>>> rollover effects and there are tricky promotion rules for
> >>>>> mixed-signedness arithmetic expressions. Unless unsignedness is
> >>>>> strongly needed, I would avoid those types.
>
> >>>> Well, call me strict, but I happen to believe that, for
> >>>> specifying sizes, unsignedness is strongly needed.

why?

> >>>> I also
> >>>> believe that, if a positive value is needed in order to
> >>>> call a function, the function's interface should say so.

ok. DbC and all that

> >>> But that doesn't save you from anyone passing a -5, as that will
> >>> "work" for an unsigned parameter as well.
>
> >> Of course, it doesn't. However, it does communicate
> >> that -5 is not a valid value.

not really as you can stuff -5 into an C++ unsigned type.
The point being that C++ unsigned types have odd (though useful)
semantics


> > If you fail to communicate the function's contract to client programmers then
> > you have a problem.  

yes

> Right. Which is why I put great emphasis on communicating
> this. In the language, rather than in comments.

Alf never said comments. In fact he talks about "automatic
detection". I think he's thinking asserts or similar measures.


> > You seem to think that that communication problem can be
> > alleviated by using unsigned types in C or C++. [...]
>
> And you seem to think that communication between callers
> and callees has to happen solely through comments. (Just
> as stupid an accusation, I know. Couldn't resist, though.)

since he never said that, that makes most of the next paragraph
moot


> If communication solely through comments was fine, all
> functions should take and return only 'void*'. (Or they
> might take an ellipsis. You can communicate the number
> of arguments through comments, after all.) Since this not
> only isn't done, but frowned upon, and since the language
> even more and more develops towards the exact opposite
> (expressing of constraints directly in the language,
> instead of in comments), I conclude there's a general
> consensus that this is better.

I fwe thought this was generally true we'd be writing Ada

> > The client code programmer may have a 100% perfect understanding of your
> > function's contract, but still manage to call it with invalid arguments.
>
> > And what happens when you pass -5 to your unsigned formal argument?
>
> > The language standard then guarantees wrapping, that you get the value 2^n-5
> > where n is the number of value representation bits, and do you check for that?
> > No? I thought so.
>
> Does your implementation of
>    std::vector<T>::operator[](size_type)
> check whether you pass -5 into it?

I believe there are checking versions. The STL generally
emphasises speed. It's up to you to validate arguments before you
pass
them to the STL. You wouldn't read the index from a terminal and then
pass it to the STL would you?


> No? I thought so.
> And what happens if you do anyway? Right. I thought so,
> too.
> And if you manage to still get this wrong even though
> you have a 100% perfect understanding of the fact that
> the operator requires an unsigned? See. Again, I thought
> so.


--
Nick Keighley

Nick Keighley

unread,
Jul 9, 2009, 4:24:46 AM7/9/09
to
On 7 July, 12:43, James Kanze <james.ka...@gmail.com> wrote:
> On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
> > James Kanze wrote:
> > > On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> > >> Lars Tetzlaff wrote:

> > >>> template <class T>
> > >>> data<T>::data(int in_n, T* in_data)
> > >>> : m_data( in_data, in_data + in_n )
> > >>> {
> > >>> }
>
> > >> Why 'int'? Will there ever be a sequence of -5 bytes?
>
> > > Because int is the "standard" type for integral values in
> > > C++.  Anything else should only be used if int won't do the
> > > job; the only justification for not using int here would be
> > > that there might be sequences of more that INT_MAX bytes.
>
> > You state this as an axiom.
>
> Because it is an axiom.  It's part of the original definition of
> C.

I don't recall this (and *I* have read the ANSI C standard). You
seemed to be stating a *design* axiom. That you use int unless there
is a reason to the contrary. I don't see this being part of the
original
language definition. It may be sensible but I don't see it as being
axiomatic.


<snip>


--
Nick keighley

James Kanze

unread,
Jul 9, 2009, 5:37:58 AM7/9/09
to
On Jul 9, 10:24 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

> On 7 July, 12:43, James Kanze <james.ka...@gmail.com> wrote:
> > On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
> > > James Kanze wrote:
> > > > On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> > > >> Lars Tetzlaff wrote:
> > > >>> template <class T>
> > > >>> data<T>::data(int in_n, T* in_data)
> > > >>> : m_data( in_data, in_data + in_n )
> > > >>> {
> > > >>> }

> > > >> Why 'int'? Will there ever be a sequence of -5 bytes?

> > > > Because int is the "standard" type for integral values in
> > > > C++. Anything else should only be used if int won't do the
> > > > job; the only justification for not using int here would be
> > > > that there might be sequences of more that INT_MAX bytes.

> > > You state this as an axiom.

> > Because it is an axiom. It's part of the original
> > definition of C.

> I don't recall this (and *I* have read the ANSI C standard).

The ISO C standard isn't the original definition of C.
Kernighan and Richie are (but I think you've read them as well).
The original C didn't even have unsigned. (It was added, along
with long, before the K&R book was published, however. I don't
have my copy of the book handy to verify, but I do seem to
remember something about "int being the natural type" in there.)

> You seemed to be stating a *design* axiom. That you use int
> unless there is a reason to the contrary. I don't see this
> being part of the original language definition. It may be
> sensible but I don't see it as being axiomatic.

Well, the committee did redefine it (at least compared to the
compilers I was using at the time, including Johnson's pcc) in a
way that means that you can't effectively mix it with signed
integers, so that things like "someUnsigned < -5" may be true.
Which certainly implies that they didn't mean for it to be used
for numeric values.

I'm not sure what Kernighan and Richie intended when they first
introduced it. But at least the compilers I used which came
from AT&T at the time did interpret "someUnsigned < -5" as
always false. (At least as I remember it. It's been quite some
time since I've used pcc.)

Pete Becker

unread,
Jul 9, 2009, 8:59:45 AM7/9/09
to
James Kanze wrote:
>
> The ISO C standard isn't the original definition of C.
> Kernighan and Richie are (but I think you've read them as well).
> The original C didn't even have unsigned. (It was added, along
> with long, before the K&R book was published, however. I don't
> have my copy of the book handy to verify, but I do seem to
> remember something about "int being the natural type" in there.)
>

"A ��plain�� int object has the natural size suggested by the
architecture of the execution environment...."

From the C99 standard, 6.2.5/5.

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

Hendrik Schober

unread,
Aug 4, 2009, 2:18:06 PM8/4/09
to
Nick Keighley wrote:
> On 8 July, 10:37, Hendrik Schober <spamt...@gmx.de> wrote:
> [old debate generously snipped]

>>
>> Does your implementation of
>> std::vector<T>::operator[](size_type)
>> check whether you pass -5 into it?
>
> I believe there are checking versions. [...]

I wonder how they check this.

> [...]
> Nick Keighley

Schobi

Hendrik Schober

unread,
Aug 4, 2009, 2:22:47 PM8/4/09
to
Paavo Helde wrote:
> Hendrik Schober <spam...@gmx.de> kirjutas:
> [...]
>
>>> The point is that when you get experienced enough, you start to
>>> understand the deficiencies of the language, and what is the best way
>>> to use the language. I know I myself believed many years ago that
>>> using 'unsigned' is a good way to communicate the information that
>>> the paramater may not be negative, and unfortunately I'm still stuck
>>> with the interfaces I wrote that time, because of backward
>>> compatibility concerns.
>> Like in the std lib, right?
>
> Yes, the use of size_t and its friends in STL also causes some headaches.

Do they? I don't think they ever caused me any headaches.

> Well, I try to bring you an example. [example deleted]


>
> Everything seems to work initially, no warnings from compiler. However,
> when used with inital data
>
> rc_left=-500
> rc_width=200
> bbox_left=-100;
> bbox_width=50;
>

> the end results for the rectangle will be -100 and 200. How comes? [...]

You mixed signed and unsigned values in your expressions.

> When you have had a similar bug in your code, and wasted lots of time
> finding and understanding it, then you would start to understand why the

> unsigned types are not so harmless in C++. [...]

I haven't ran into this in more than a decade.
I understand this just shows I'm not experienced enough.

> Best regards
> Paavo

Schobi

Hendrik Schober

unread,
Aug 4, 2009, 2:29:34 PM8/4/09
to
James Kanze wrote:
> On Jul 7, 4:05 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>> James Kanze wrote:
>>> On Jul 7, 11:08 am, Hendrik Schober <spamt...@gmx.de> wrote:
>>>> James Kanze wrote:
>>>>> On Jul 5, 10:39 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>>>>>> Lars Tetzlaff wrote:
>>>>> [...]
>>>>>>> template <class T>
>>>>>>> data<T>::data(int in_n, T* in_data)
>>>>>>> : m_data( in_data, in_data + in_n )
>>>>>>> {
>>>>>>> }
>
>>>>>> Why 'int'? Will there ever be a sequence of -5 bytes?
>
>>>>> Because int is the "standard" type for integral values in
>>>>> C++. Anything else should only be used if int won't do
>>>>> the job; the only justification for not using int here
>>>>> would be that there might be sequences of more that
>>>>> INT_MAX bytes.
>
>>>> You state this as an axiom.
>
>>> Because it is an axiom. It's part of the original
>>> definition of C.
>
>> Mhmm. I've never owned a C standard, so I only know from
>> hearsay, but so far I always assumed 'int' was "the native
>> integer type on the platform",
>
> And how is this different from "the standard type"?

What is "standard", is defined, what is "native" is given?

> [...]
>>> To be reasonable, you need to include behavior in the
>>> representation. If the data is natural, positive numbers,
>>> subtraction can still result in a negative value [...]
>
>> Yep. And when dividing with 'double', you have to be
>> careful, since a '0.0' might be fatal. What's the
>> fundamental different to subtracting unsigned integers?
>
> Because there's no relationship whatsoever between them. The
> subtraction of two natural numbers is a well defined operation;

...that has a result which cannot be represented by
a natural number. <shrug>

> [...]


>
>>> In the end, a language is designed the way it is designed. You
>>> can fight it, but you won't win. Kernighan and Richie decided
>>> that the principal integral type in C would be int; all other
>>> types have been added for specific needs, but int remains THE
>>> integral type. Anytime you use anything else (for integral
>>> values, of course), you're fighting the language: introducing
>>> additional complexity and additional possibilities for errors.
>
>> Mhmm. Then who added 'size_t' to be used for sizes
>> to this language?
>
> I don't know. That came a lot later. (Don't forget, however,
> that size_t was originally designed to represent something very
> low level, which often wouldn't fit in an int.)

It is recycled throughout most of the C++ std lib (as
'size_type').
I know, I know, that, too, came a lot later. So did I.
And why is this an argument? And if it is, isn't it in
favor of 'size_t'?

Schobi

Greg Herlihy

unread,
Aug 4, 2009, 7:10:26 PM8/4/09
to
On Aug 4, 11:29 am, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> >> Yep. And when dividing with 'double', you have to be
> >> careful, since a '0.0' might be fatal. What's the
> >> fundamental different to subtracting unsigned integers?
>
> > Because there's no relationship whatsoever between them.  The
> > subtraction of two natural numbers is a well defined operation;
>
> ...that has a result which cannot be represented by
> a natural number. <shrug>

In C++, the difference between any two unsigned numbers is always
another unsigned number. So the reason why an unsigned type is such a
poor choice to represent a natural number - is because an unsigned
type does not behave like a natural number. And since representing
data is as much about representing behavior as it is about
representing a value - it should be clear that - when representing
numeric values - an unsigned type should always be the choice of last
resort.

Greg

James Kanze

unread,
Aug 5, 2009, 5:32:01 AM8/5/09
to

They don't have to. It's impossible. size_type must be
unsigned, so there's no possible way to pass a -5 through it.

Of course, the results of converting -5 to size_type are going
to be a very larger number. Almost (but not quite) surely large
enough, in most cases, that it will be out of bounds.

James Kanze

unread,
Aug 5, 2009, 5:44:53 AM8/5/09
to
On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:

[...]


> > Because there's no relationship whatsoever between them. The
> > subtraction of two natural numbers is a well defined operation;

> ...that has a result which cannot be represented by
> a natural number. <shrug>

Exactly. And if the language defines a type T such that T - T
-> T, then that type isn't an abstraction of the natural
numbers. For a type to be usable as an abstraction of the
natural numbers, the results of subtraction must be another
type, or subtraction must not be supported. (Modula-2, for
example, takes that latter course.) C++ doesn't have such a
type; the closest we can come is int.

> > [...]
> >>> In the end, a language is designed the way it is designed. You
> >>> can fight it, but you won't win. Kernighan and Richie decided
> >>> that the principal integral type in C would be int; all other
> >>> types have been added for specific needs, but int remains THE
> >>> integral type. Anytime you use anything else (for integral
> >>> values, of course), you're fighting the language: introducing
> >>> additional complexity and additional possibilities for errors.

> >> Mhmm. Then who added 'size_t' to be used for sizes
> >> to this language?

> > I don't know. That came a lot later. (Don't forget, however,
> > that size_t was originally designed to represent something very
> > low level, which often wouldn't fit in an int.)

> It is recycled throughout most of the C++ std lib (as
> 'size_type').

I know. That's obviously an error in the conception of the
library, but it's too late to change it now, despite the
problems it causes.

Hendrik Schober

unread,
Aug 5, 2009, 6:10:21 AM8/5/09
to
James Kanze wrote:
> On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>
> [...]
>>> Because there's no relationship whatsoever between them. The
>>> subtraction of two natural numbers is a well defined operation;
>
>> ...that has a result which cannot be represented by
>> a natural number. <shrug>
>
> Exactly. And if the language defines a type T such that T - T
> -> T, then that type isn't an abstraction of the natural
> numbers. For a type to be usable as an abstraction of the
> natural numbers, the results of subtraction must be another
> type, or subtraction must not be supported. (Modula-2, for
> example, takes that latter course.) C++ doesn't have such a
> type; the closest we can come is int.

Mhmm. You got me thinking here.

>>> [...]
>>>>> In the end, a language is designed the way it is designed. You
>>>>> can fight it, but you won't win. Kernighan and Richie decided
>>>>> that the principal integral type in C would be int; all other
>>>>> types have been added for specific needs, but int remains THE
>>>>> integral type. Anytime you use anything else (for integral
>>>>> values, of course), you're fighting the language: introducing
>>>>> additional complexity and additional possibilities for errors.
>
>>>> Mhmm. Then who added 'size_t' to be used for sizes
>>>> to this language?
>
>>> I don't know. That came a lot later. (Don't forget, however,
>>> that size_t was originally designed to represent something very
>>> low level, which often wouldn't fit in an int.)
>
>> It is recycled throughout most of the C++ std lib (as
>> 'size_type').
>
> I know. That's obviously an error in the conception of the
> library, but it's too late to change it now, despite the
> problems it causes.

I'm still not convinced, the choice of unsigned for counting
objects throughout the whole std lib is wrong.

Schobi

Richard Herring

unread,
Aug 5, 2009, 7:34:41 AM8/5/09
to
In message <h5bm2t$cdc$1...@hoshi.visyn.net>, Hendrik Schober
<spam...@gmx.de> writes

[If you'll forgive a linguistic nitpick, that's ambiguous in English. I
take it you mean you're not convinced *that* the choice of unsigned is
wrong. ]

It's fine for *counting*. The problem is that it's used for several
other things as well. An index is not a count, though it can be mapped
to one. The difference of two indices is definitely not a count.
--
Richard Herring

Hendrik Schober

unread,
Aug 5, 2009, 9:35:55 AM8/5/09
to
Richard Herring wrote:
> In message <h5bm2t$cdc$1...@hoshi.visyn.net>, Hendrik Schober <spam...@gmx.de> writes
>> James Kanze wrote:
>>> On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> [generously snipping]

>>>>>> Mhmm. Then who added 'size_t' to be used for sizes
>>>>>> to this language?
>>>>> I don't know. That came a lot later. (Don't forget, however,
>>>>> that size_t was originally designed to represent something very
>>>>> low level, which often wouldn't fit in an int.)
>>>> It is recycled throughout most of the C++ std lib (as
>>>> 'size_type').
>>> I know. That's obviously an error in the conception of the
>>> library, but it's too late to change it now, despite the
>>> problems it causes.
>> I'm still not convinced, the choice of unsigned for counting
>> objects throughout the whole std lib is wrong.
>
> [If you'll forgive a linguistic nitpick, that's ambiguous in English. I
> take it you mean you're not convinced *that* the choice of unsigned is
> wrong. ]

[Thanks. Actually I wish I was corrected more. How could I
improve otherwise. And, yes, your guess was correct.]

> It's fine for *counting*. The problem is that it's used for several
> other things as well. An index is not a count, though it can be mapped
> to one. The difference of two indices is definitely not a count.

Wait. I see that the difference between two indices should
not be expressed as an unsigned value. But what is this
about an index? Are you saying an index shouldn't be an
unsigned value?

Schobi

Richard Herring

unread,
Aug 5, 2009, 10:27:08 AM8/5/09
to
In message <h5c1rs$g1o$1...@hoshi.visyn.net>, Hendrik Schober
>>one. The difference of two indices is definitely not a count.
>
>Wait. I see that the difference between two indices should
>not be expressed as an unsigned value. But what is this
>about an index? Are you saying an index shouldn't be an
>unsigned value?

No. Just that an index is not quite the same kind of thing as a count.
Don't forget that there are languages where indexes don't start at 0 (or
even 1;-)

--
Richard Herring

Hendrik Schober

unread,
Aug 5, 2009, 11:10:57 AM8/5/09
to

Yep, I remember wanting to type 'index_type' quite often
when I learned to use the STL.

> Don't forget that there are languages where indexes don't start at 0 (or
> even 1;-)

Yes, and if it started at negative values (ISTR that Ada
allowed specifying arbitrary index ranges for arrays), a
signed integer would be advisable.

Schobi

James Kanze

unread,
Aug 6, 2009, 4:23:57 AM8/6/09
to
On Aug 5, 12:10 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> > On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>
> > [...]
> I'm still not convinced, the choice of unsigned for counting
> objects throughout the whole std lib is wrong.

If all we did was count them, there'd be no problem. The
problems start when we start subtracting pointers or iterators.

In C++ (and C), there are also problems when mixing the types,
because the implicit conversions are signedness preserving, not
value preserving. The C committee doubtlessly had some reason
for doing this (earlier C compilers were value preserving), but
it does cause some confusing results when comparing values with
different types:
unsigned u = 10 ;
if ( u > -5 ) // ...
Logically, the if should always be true, but in fact, in the
above case, it's false. Good compilers warn about this,
however, and you can (and should) explicitly convert to
whichever is more appropriate, e.g.:
unsigned u = 10 ;
if ( static_cast< int >( u ) > -5 ) // ...
// or checked_cast, if you can't guarantee that
// u is representable as an int.
Still, having to do so is a pain; it's much easier to just use
int everywhere. (Alternatively, a language could support ranged
types, with range checking. All conversions would be value
preserving, or cause a bound check error.)

Alf P. Steinbach

unread,
Aug 6, 2009, 4:32:16 AM8/6/09
to
* James Kanze:

> On Aug 5, 12:10 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>> James Kanze wrote:
>>> On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:
>>> [...]
>> I'm still not convinced, the choice of unsigned for counting
>> objects throughout the whole std lib is wrong.
>
> If all we did was count them, there'd be no problem. The
> problems start when we start subtracting pointers or iterators.
>
> In C++ (and C), there are also problems when mixing the types,
> because the implicit conversions are signedness preserving, not
> value preserving.

I think you meant to write the opposite, yes?


> The C committee doubtlessly had some reason
> for doing this (earlier C compilers were value preserving), but
> it does cause some confusing results when comparing values with
> different types:
> unsigned u = 10 ;
> if ( u > -5 ) // ...

E.g., how does this preserve the signedness of the -5?

James Kanze

unread,
Aug 6, 2009, 6:17:26 AM8/6/09
to
On Aug 6, 10:32 am, "Alf P. Steinbach" <al...@start.no> wrote:
> * James Kanze:

> > On Aug 5, 12:10 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> >> James Kanze wrote:
> >>> On Aug 4, 8:29 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> >>> [...]
> >> I'm still not convinced, the choice of unsigned for counting
> >> objects throughout the whole std lib is wrong.

> > If all we did was count them, there'd be no problem. The
> > problems start when we start subtracting pointers or iterators.

> > In C++ (and C), there are also problems when mixing the types,
> > because the implicit conversions are signedness preserving, not
> > value preserving.

> I think you meant to write the opposite, yes?

No. The implicit conversions do not preserve the value. What I
actually should have written is "unsigned preserving" vs. "value
preserving". See §3.2.1.1 of the Rationale for C
(http://www.quut.com/c/rat/title.html).

(Curiously enough, the Rationale justifies choosing value
preserving semantics over unsigned preserving, but the C
standard, and C++ after it, do just the opposite. But this
section is speaking mainly about things like unsigned short to
int or to unsigned int. And confuses me more than anything
else. But misremembered, it is my source for the terminology.)

0 new messages