473,372 Members | 1,082 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,372 software developers and data experts.

negative number evaluating greater than string.size()

Hi, below is example code which demonstrates a problem I have encountered.
When passing a number to a function I compare it with a string's size and
then take certain actions, unfortunately during the testing of it I
discovered that negative numbers were being treated as if they were > 0. I
compiled the following on mingw compiler/dev c++/windows xp.

If I replace string.size() for a ordinary number it behaves as expected? I
notice string.size() returns size type and not an int but how do I deal with
that?

Thanks in advance for any help

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;

void something(int);

int main()
{
something(-1);
system("PAUSE");
return 0;
}

void something(int number) {
string str = "sdfjksdflksdjfkjsklfjsklfj";
if(number < str.size()) { cout << " hello" << endl; }
else { cout << " eek" << endl; }
}
Jul 22 '05 #1
25 2933
Jason wrote:
Hi, below is example code which demonstrates a problem I have encountered.
When passing a number to a function I compare it with a string's size and
then take certain actions, unfortunately during the testing of it I
discovered that negative numbers were being treated as if they were > 0. I
compiled the following on mingw compiler/dev c++/windows xp.

If I replace string.size() for a ordinary number it behaves as expected? I
notice string.size() returns size type and not an int but how do I deal with
that?

Thanks in advance for any help


GCC sez:

signed_probs.cpp: In function `void something(int)':
signed_probs.cpp:17: warning: comparison between signed and unsigned
integer expressions

Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.
Jul 22 '05 #2

"Jason" <ja***********@btinternet.com> wrote in message
news:c1**********@titan.btinternet.com...
Hi, below is example code which demonstrates a problem I have encountered.
When passing a number to a function I compare it with a string's size and
then take certain actions, unfortunately during the testing of it I
discovered that negative numbers were being treated as if they were > 0. I compiled the following on mingw compiler/dev c++/windows xp.

If I replace string.size() for a ordinary number it behaves as expected? I notice string.size() returns size type and not an int but how do I deal with that?


Suggest you read the recent thread 'time to get rid of unsigned?', started
on 17/02/04.

john
Jul 22 '05 #3

"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:c1********@dispatch.concentric.net...
Jason wrote:
Hi, below is example code which demonstrates a problem I have encountered. When passing a number to a function I compare it with a string's size and then take certain actions, unfortunately during the testing of it I
discovered that negative numbers were being treated as if they were > 0. I compiled the following on mingw compiler/dev c++/windows xp.

If I replace string.size() for a ordinary number it behaves as expected? I notice string.size() returns size type and not an int but how do I deal with that?

Thanks in advance for any help


GCC sez:

signed_probs.cpp: In function `void something(int)':
signed_probs.cpp:17: warning: comparison between signed and unsigned
integer expressions

Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.


Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design for such
strings in the first place? Why not have size() return an int?

john

Jul 22 '05 #4
John Harrison wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:c1********@dispatch.concentric.net...

signed_probs.cpp: In function `void something(int)':
signed_probs.cpp:17: warning: comparison between signed and unsigned
integer expressions

Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.

Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design for such
strings in the first place? Why not have size() return an int?


Because its more flexible to have a type where someone can
hold a string thats over 2Gb in size. I remember something
like this being used as a justification for making size_t
unsigned some 15 years back, either in GCC documentation or
the "Standard C library", in relation to malloc().

Naturally someone will tell you that you should be coding
everything that deals with sizes and lengths with size_t.
Jul 22 '05 #5

"lilburne" <li******@godzilla.net> wrote in message
news:c1*************@ID-179504.news.uni-berlin.de...
John Harrison wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:c1********@dispatch.concentric.net...

signed_probs.cpp: In function `void something(int)':
signed_probs.cpp:17: warning: comparison between signed and unsigned
integer expressions

Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }
solves the problem.
Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design for such strings in the first place? Why not have size() return an int?


Because its more flexible to have a type where someone can
hold a string thats over 2Gb in size. I remember something
like this being used as a justification for making size_t
unsigned some 15 years back, either in GCC documentation or
the "Standard C library", in relation to malloc().


Interestingly the following code

int main()
{
std::string s;
std::cout << std::hex << s.max_size() << '\n';
}

when compiled with gcc 3.3.1 prints

3ffffffc

I don't think its a serious limitation to restrict yourself to strings which
occupy less than half of the available memory.

Naturally someone will tell you that you should be coding
everything that deals with sizes and lengths with size_t.


But what happens when you need to subtract one size from another? What type
should be used to hold the type of that operation? I don't think there is a
good answer.

john
Jul 22 '05 #6
> What type should be used to hold the type of that operation?

I meant

What type should be used to hold the result of that operation?
Jul 22 '05 #7
lilburne wrote:
Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design
for such strings in the first place? Why not have size() return an
int?


Because its more flexible to have a type where someone can
hold a string thats over 2Gb in size.


I think it's not. You'd run into troubles if you need to calculate
offsets between two characters in your string. That offset might be
negative. Now you can't represent all possible offests anymore, no
matter whether you make the type for that offset signed or unsigned.
And further, if you mix signed and unsigned in your calculations, you
have to be very careful.

Jul 22 '05 #8
"John Harrison" <jo*************@hotmail.com> wrote in news:c13cvl$1dskq6$1
@ID-196037.news.uni-berlin.de:
What type should be used to hold the type of that operation?


I meant

What type should be used to hold the result of that operation?


size_t, assuming the programmer has done the sane thing and checked that
they are actually subtracting the smaller from the larger.
Jul 22 '05 #9
John Harrison wrote:
...
Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.


Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design for such
strings in the first place? Why not have size() return an int?
...


In my opinion, using a signed type to store an unsigned quantity is a
low-level design error. For this reason, in many practical applications
signed types in C/C++ are much less useful than unsigned types. And
'size()' must return an unsigned value.

As for correcting the OP's code, I would suggest doing it differently

if (number < 0 || (std::string::size_type) number < str.size())
{ cout << " hello" << endl; }

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #10
Rolf Magnus wrote:
lilburne wrote:

Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design
for such strings in the first place? Why not have size() return an
int?

Because its more flexible to have a type where someone can
hold a string thats over 2Gb in size.

I think it's not.

I think so too.

You'd run into troubles if you need to calculate
offsets between two characters in your string. That offset might be
negative. Now you can't represent all possible offests anymore, no
matter whether you make the type for that offset signed or unsigned.
And further, if you mix signed and unsigned in your calculations, you
have to be very careful.


I think it was for the reasons of inadvertantly mixing
signed and unsigned that Lakos recommended avoiding unsigned
in interfaces in "Large Scale C++".

Jul 22 '05 #11

"Andre Kostur" <nn******@kostur.net> wrote in message
news:Xn*******************************@207.35.177. 135...
"John Harrison" <jo*************@hotmail.com> wrote in news:c13cvl$1dskq6$1 @ID-196037.news.uni-berlin.de:
What type should be used to hold the type of that operation?


I meant

What type should be used to hold the result of that operation?


size_t, assuming the programmer has done the sane thing and checked that
they are actually subtracting the smaller from the larger.


It gets very tedious after a while.

size_t size_a = ...;
size_t size_b = ...;
size diff;
bool a_is_bigger;
if (a > b)
{
diff = size_a - size_b;
a_is_bigger = true;
}
else
{
diff = size_b - size_a;
a_is_bigger = false;
}
process_diff(diff, a_is_bigger);

and hence its prone to errors, as we have all seen. In fact I very rarely
see code that takes this much trouble. It would be easier if size_t was
defined as a signed integer, and not a great deal would have been lost.

john

Jul 22 '05 #12
John Harrison wrote:
...
It would be easier if size_t was
defined as a signed integer, and not a great deal would have been lost.
...


It wouldn't solve anything. It would just made the problem less obvious.
In general case the difference between two signed integers does not fit
into the range of the same signed integer type. The resultant signed
type must be at least one bit longer than original types.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #13

"Andrey Tarasevich" <an**************@hotmail.com> wrote in message
news:Ft********************@comcast.com...
John Harrison wrote:
...
It would be easier if size_t was
defined as a signed integer, and not a great deal would have been lost.
...


It wouldn't solve anything. It would just made the problem less obvious.
In general case the difference between two signed integers does not fit
into the range of the same signed integer type. The resultant signed
type must be at least one bit longer than original types.


When that integer represents the size of something, it can only be positive
or zero. If it always possible to subtract two such positive signed numbers
without overflow. That's obvious isn't it?

john
Jul 22 '05 #14
John Harrison wrote:
> ...
> It would be easier if size_t was
> defined as a signed integer, and not a great deal would have been lost.
> ...


It wouldn't solve anything. It would just made the problem less obvious.
In general case the difference between two signed integers does not fit
into the range of the same signed integer type. The resultant signed
type must be at least one bit longer than original types.


When that integer represents the size of something, it can only be positive
or zero. If it always possible to subtract two such positive signed numbers
without overflow. That's obvious isn't it?
...


Yes, but the trade-off in this case is that you can only use half of the
type's range.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #15
John Harrison wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:c1********@dispatch.concentric.net...
Jason wrote:
Hi, below is example code which demonstrates a problem I have encountered. When passing a number to a function I compare it with a string's size and then take certain actions, unfortunately during the testing of it I discovered that negative numbers were being treated as if they were > 0. I compiled the following on mingw compiler/dev c++/windows xp. If I replace string.size() for a ordinary number it behaves as expected? I
notice string.size() returns size type and not an int but how do I deal with that? Thanks in advance for any help

<reinserted>

void something(int number) {
if(number < str.size()) { /*...*/ }
}

</>
GCC sez:

signed_probs.cpp: In function `void something(int)':
signed_probs.cpp:17: warning: comparison between signed and unsigned
integer expressions

Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.

Of course this is what the OP should do,


No, an unnecessary cast is not what the OP should do. The problem is
that a signed "number" is being compared to an unsigned "size." "int"
and "string::size_type" are not the same thing; they are not always
comparable. A more reasonable solution would be for "number" to be of
string::size_type in the first place, or of a signed type that knows how
to compare itself with string::size_type.

Jul 22 '05 #16
lilburne wrote:
I think it was for the reasons of inadvertantly mixing
signed and unsigned that Lakos recommended avoiding unsigned
in interfaces in "Large Scale C++".


Same for Stroustup in TC++PL. Strange enough that size_t is unsinged,
since Stroustrup probably had to do something with it. In the book, he
writes:

"The unsigned integer types are ideal for uses that treat storage as a
bit array. Using an unsigned instead of an int to gain one more bit to
represent positive integers is almost never a good idea. Attempts to
ensure that some values are positive by declaring variables unsigned
will typically be defeated by the implicit conversion rules."
Jul 22 '05 #17


Jeff Schwab wrote:

No, an unnecessary cast is not what the OP should do. The problem is
that a signed "number" is being compared to an unsigned "size." "int"
and "string::size_type" are not the same thing; they are not always
comparable. A more reasonable solution would be for "number" to be of
string::size_type in the first place, or of a signed type that knows how
to compare itself with string::size_type.


Naturally! And std::vector::size_type, std::list::size_type,
std::deque::size_type, std::set::size_type, std::map::size_type, etc,
whenever dealing with the corresponding class. Maybe they'll all be the
same underlaying type, but who can tell?

Jul 22 '05 #18
lilburne wrote:


Jeff Schwab wrote:

No, an unnecessary cast is not what the OP should do. The problem is
that a signed "number" is being compared to an unsigned "size." "int"
and "string::size_type" are not the same thing; they are not always
comparable. A more reasonable solution would be for "number" to be of
string::size_type in the first place, or of a signed type that knows
how to compare itself with string::size_type.

Naturally! And std::vector::size_type, std::list::size_type,
std::deque::size_type, std::set::size_type, std::map::size_type, etc,
whenever dealing with the corresponding class.


That's right.
Maybe they'll all be the
same underlaying type, but who can tell?


A specialized template can.

Jul 22 '05 #19
Andrey Tarasevich wrote:
John Harrison wrote:
...
Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" <<
endl; }

solves the problem.


Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design
for such strings in the first place? Why not have size() return an
int? ...


In my opinion, using a signed type to store an unsigned quantity is a
low-level design error.


In mine, it's a design error to use an unsigned type if you don't have a
very good reason to do so. That you only want to store non-negative
values is not such a reason.
Why is there no unsigned floating point type, just for the case you want
to store only postive values?

Jul 22 '05 #20
Rolf Magnus wrote:
...
In my opinion, using a signed type to store an unsigned quantity is a
low-level design error.
In mine, it's a design error to use an unsigned type if you don't have a
very good reason to do so. That you only want to store non-negative
values is not such a reason.


Well, looks like we have different opinions on the subject.
Why is there no unsigned floating point type, just for the case you want
to store only postive values?


For several reasons. It is much more difficult to provide
implementation-level support for an additional floating-point type than
for an additional integral type in situations when the underlying
hardware does not support it. Additionally, aside from purely conceptual
reasons, there is very little benefit from one extra mantissa (or
exponent) bit in a floating-point type. Under these circumstances, since
most hardware does not provide support for unsigned floating-point
types, it is not reasonable to force these types into language.

BTW, the reasons for domination of signed integral types in certain
arithmetical contexts in C (inherited into C++, like integral promotions
from smaller types) are probably very similar.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #21
>
Suggest you read the recent thread 'time to get rid of unsigned?', started
on 17/02/04.

john


I read all the whining about unsigned, and still disagree....

Regardless, what sense does it make to have a string with size < 0?
Furthermore, he should have been using
void something(std::string::size_type)
to start with.

In my mind, this is just a problem of people not reading the standard
documentation.

The least programmers should do is see the header files to understand
what types are being used, not just trust their instincts.
Jul 22 '05 #22

"Jorge Rivera" <jo*****@rochester.rr.com> wrote in message
news:1N*******************@twister.nyroc.rr.com...

Suggest you read the recent thread 'time to get rid of unsigned?', started on 17/02/04.

john
I read all the whining about unsigned, and still disagree....

Regardless, what sense does it make to have a string with size < 0?


That's not the point. Apparaently both Stroustrup and Lakos recomend
avoiding using unsigned for the size of something because of the potential
overflow problems, particularly (in my view) when one unsigned quantity has
to be subtracted from another.
Furthermore, he should have been using
void something(std::string::size_type)
to start with.
Maybe but you cannot know the problem he was working on.

In my mind, this is just a problem of people not reading the standard
documentation.

The least programmers should do is see the header files to understand
what types are being used, not just trust their instincts.


Can't disagree with that.

john
Jul 22 '05 #23
Andrey Tarasevich <an**************@hotmail.com> wrote in message news:<10*************@news.supernews.com>...
John Harrison wrote:
...
Changing line 17 to :

if(number < static_cast<int>(str.size())) { cout << " hello" << endl; }

solves the problem.


Of course this is what the OP should do, but notice that the solution
effectively rules out strings where size() > INT_MAX. So why design for such
strings in the first place? Why not have size() return an int?
...


In my opinion, using a signed type to store an unsigned quantity is a
low-level design error.


What does unsigned gain you? If you use signed and write code with a
bug, you could end up calculating someone's age as -1 years. If you
use unsigned and write the same code with the same bug you end up with
the age as 4294967295 years (assuming 32 bits as an example). Who
cares that one of those numbers happens to be >0? They are both as
wrong as the other. The code needs to be fixed whether age is signed
or unsigned, and once it is fixed, it will work whether age is signed
or unsigned.

--
GJD
Jul 22 '05 #24
Jorge Rivera <jo*****@rochester.rr.com> wrote in message news:<1N*******************@twister.nyroc.rr.com>. ..

Suggest you read the recent thread 'time to get rid of unsigned?', started
on 17/02/04.

john
I read all the whining about unsigned, and still disagree....

Regardless, what sense does it make to have a string with size < 0?


You missed the point. With a signed string size type, any code that
ends up with a size < 0 has a bug. If that same code had been written
with an unsigned string size type, it would still have a bug. The
garbage size value would now happen to be > 0, but so what? That
doesn't make the code any more correct. It is the same bug,
manifesting itself in a different way.

--
GJD
Furthermore, he should have been using
void something(std::string::size_type)
to start with.

In my mind, this is just a problem of people not reading the standard
documentation.

The least programmers should do is see the header files to understand
what types are being used, not just trust their instincts.

Jul 22 '05 #25
>
You missed the point. With a signed string size type, any code that
ends up with a size < 0 has a bug. If that same code had been written
with an unsigned string size type, it would still have a bug. The
garbage size value would now happen to be > 0, but so what? That
doesn't make the code any more correct. It is the same bug,
manifesting itself in a different way.


The point is simple, read the documentation, read the correct behavior
of std::string, use it appropriately.

std::string::size_type std::string::size()

can not return a negative number. If anything, functions within
std::string will return std::string::npos, and I doubt there is any
situtation in which std::size() would return it.

Any other assumptions about values returned by string are just that,
assumptions. The behavior of the class is what it is, and we all should
just play by its rules, not whine weahter the implementation is signed
or unsigned.

JLR

Jul 22 '05 #26

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Tripp Knightly | last post by:
I have a lookup table from which I want to categorize various bands of customer net income. Some of the income is positive, some is negative. The bands vary in size (ie, <500, -200 to 0, 100 to...
11
by: John | last post by:
Hi, I encountered a strange problem while debugging C code for a Windows-based application in LabWindows CVI V5.5, which led me to write the test code below. I tried this code with a different...
23
by: Davey | last post by:
How do I display an integer in binary format in C? e.g. 4 displayed as "100"
11
by: tlyczko | last post by:
Hello Rob B posted this wonderful code in another thread, http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/c84d8538025980dd/6ead9d5e61be85f0#6ead9d5e61be85f0 I could not...
7
by: andreas.lydersen | last post by:
Hi! While communicating with a monitoring unit, I get some hex values representing degrees celcius from its probes. The values can be something like '19' or '7d'. To convert it to int, I do the...
11
by: drtimhill | last post by:
I'm just starting out on Python, and am stumped by what appears an oddity in the way negative indices are handled. For example, to get the last character in a string, I can enter "x". To get the...
39
by: Frederick Gotham | last post by:
I have a general idea about how negative number systems work, but I'd appreciate some clarification if anyone would be willing to help me. Let's assume we're working with an 8-Bit signed integer,...
3
by: hello2008 | last post by:
Hi, I donot have much knowledge of R.Exp. In my web page I am required to validate numeric textboxes allowing signed/unsigned integer/float numbers and then compare between them. I need the...
6
by: shashi shekhar singh | last post by:
Respected Sir, I am facing problem when i try to deploy my website on iis 7.0 on test page. i have to display some .mht files on iframe in gridview and error looks like below, Server Error in...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.