String - substr query

S

sks

Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)
My questions are :
1. Is this behaviour correct ? ( Or should this case be an exception?)
2. If it is correct, what is the idea behind this behaviour ?

using namespace std;
#include <iostream>
#include <string>
int main()
{
string s("This is a test string");
cout << s.substr(0,-1) << endl;
return 0;
}


Thanks,
Sumedha Swamy
 
D

Daniel T.

"sks said:
Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)
My questions are :
1. Is this behaviour correct ? ( Or should this case be an exception?)
Yes.

2. If it is correct, what is the idea behind this behaviour ?

using namespace std;
#include <iostream>
#include <string>
int main()
{
string s("This is a test string");
cout << s.substr(0,-1) << endl;
return 0;
}

basic_string basic_string::substr(size_type pos = 0, size_type n = npos)
const

Constructs a string from a substring of s. The substring begins at
character position pos and terminates at character position pos + n or
at the end of s, whichever comes first.

Note that n is of type size_type which is unsigned, so passing -1
probably makes for a very big number.
 
N

Noah Roberts

sks said:
Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)

There is no such thing as a substr parameter lesser than 0 as the param
type is unsigned.
My questions are :
1. Is this behaviour correct ? ( Or should this case be an exception?)
2. If it is correct, what is the idea behind this behaviour ?

using namespace std;
#include <iostream>
#include <string>
int main()
{
string s("This is a test string");
cout << s.substr(0,-1) << endl;

Passed parameter is not -1 but a very large positive number on most
architectures.
 
K

Kai-Uwe Bux

sks said:
Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)
My questions are :
1. Is this behaviour correct ? ( Or should this case be an exception?)
Somewhat.

2. If it is correct, what is the idea behind this behaviour ?

The idea is that substr() should return the whole string if the second
argument is larger than the length of the string.
using namespace std;
#include <iostream>
#include <string>
int main()
{
string s("This is a test string");
cout << s.substr(0,-1) << endl;
return 0;
}

The signature of substr() is:

basic_string<charT,traits,Allocator>
substr(size_type pos = 0, size_type n = npos) const;

As you can see, the length argument is of type size_type, which is inherited
from the Allocator. You are using std::allocator<charT>, whose size_type is
std::size_t and therefore unsigned. You are passing -1, which wraps around
and yields in fact the maximum number that can be represented.


Best

Kai-Uwe Bux
 
J

Jim Langston

sks said:
Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)
My questions are :
1. Is this behaviour correct ? ( Or should this case be an exception?)
2. If it is correct, what is the idea behind this behaviour ?

using namespace std;
#include <iostream>
#include <string>
int main()
{
string s("This is a test string");
cout << s.substr(0,-1) << endl;
return 0;
}


Thanks,
Sumedha Swamy

It is correct by the fact that substr's second paramter is unsigned. size_t
which (on my implementation) is a 4 byte unsigned int.

Passing a negative number as an unsigned parameter actually makes a very BIG
number. The high bit is set in signed numbers, and in unsigned the high bit
is treated as a high number. 2147483648 in a 32 bit unsigned int. If your
system uses 2's compliment (most do) -1 as a signed is the largest value the
number can hold, because all bits are set for -1 (google up on 2's
compliment to find out why).

Incidently, -1 is actually teh value used for npos (no position) which is
the largest value for size_t (all bits set).

So, saying
s.substr(0,-1)
is actually the same as saying
s.substr(0, 4294967295)

You can also achieve the exact same thing by leaving off the second parm.
s.substr(0)
If the second parm is left off, it defaults to npos which is 4294967295 on
32 bit systems.
 
J

joosteto

sks said:
Hi,

Here is a small program that is wrtten to simply use substr.
When the second parameter in substr (length of the string to be
extracted) is lesser than 0, the output is the entire string (I'm using
gcc 4.1.0)

As others pointed out, the lengt parameter of substr is size_type,
unsigned.

But being often enough enoyed by the signed/unsigned warnings of
g++/vc++, I wondered why gcc didn't warn you.

Having installed a few versions, I tried:

$ g++-2.95.4 -Wall -O2 ref.cc -o ref && ./ref
This is a test string

$ g++-3.3.6 -Wall -O2 ref.cc -o ref && ./ref
ref.cc: In function `int main()':
ref.cc:8: warning: passing negative value `-1' for converting 2 of `
std::basic_string<_CharT, _Traits, _Alloc> std::basic_string<_CharT,
_Traits, _Alloc>::substr(typename _Alloc::size_type, typename
_Alloc::size_type) const [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]'
This is a test string

$ g++-4.0.3 -Wall -O2 ref.cc -o ref && ./ref
ref.cc: In function 'int main()':
ref.cc:8: warning: passing negative value '-0x00000000000000001' for
argument 2 to 'std::basic_string<_CharT, _Traits, _Alloc>
std::basic_string<_CharT, _Traits, _Alloc>::substr(typename
_Alloc::size_type, typename _Alloc::size_type) const [with _CharT =
char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
This is a test string

$ g++-4.1.1 -Wall -O2 ref.cc -o ref && ./ref
This is a test string

So the various g++ versions somtimes warn, sometimes don't. You just
happened to use a version that doesn't. Wonder why 4.1 stopped warning
again. (It's not in the .h files, as the cpp (-E) output generated by
4.0.3 doesn't generate a warning with 4.1.1, the reverse does warn)
 
S

sks

Hi,
Thanks all of you. I'm now convinced that the behaviour is correct.
But as joosteto has pointed out, gcc should have atleast given me a
warning.

Thanks once again.

Sumedha Swamy
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top