the following code
#include <iostream>
using namespace std;
int main(){
char greeting[50] = "goodmorning everyone";
char *s1 = greeting;
char *s2 = &greeting[7];
bool test = s2-s1;
cout << "s1 is: " << s1 << endl;
cout << "s2 is: " << s2 << endl;
if (test == true ){
cout << "test is true and is: " << test << endl;
}
if (test == false){
cout<< "test is false and is: " << test << endl;
}
return 0;
}
outputs:
s1 is: goodmorning everyone
s2 is: ning everyone
test is true and is: 1
here what does the line bool test = s2-s1; actually evaluate?, is it the length of the string?. If so, then seeing as s2 is a smaller than s1 it should be negative correct?, and yet the output is true?.
Also if i change it to bool test = s1-s2; I still end up with the same result. So it doesnt matter whether its negative or positive the it will be true? and only false when 0?.
what does the s2-s1 mean?
-cheers (trying to get rid of doubts:))
If the result of the subtraction is zero, test will be false; otherwise it will be true.
Any value that is of a numeric type, enumeration type, or is a pointer can be converted to a boolean; if the value is zero (or null, for pointers), the result is false; otherwise the result is true.
Integer types, floating point types, and pointer types are all convertable to bool. For all of them, a value of 0 converts to false, and a non-zero value converts to true.
So, if s2 - s1 evaluates to 0, then test is false. Otherwise, test is true.
Since s1 and s2 are pointers, s2 - s1 is giving the difference between them (how far apart the addresses are). If they point to the same address, then the difference will be 0. If they point to different addresses, then the result will be non-zero. So, really all test indicates is whether s1 and s2 point to different addresses. s1 != s2 would give exactly the same result and would probably make more sense.
However, given that the values for s1 and s2 are hard-coded and are guaranteed to point to different addresses, the test doesn't really make any sense. It could make sense in another program though - particularly one where s1 and s2 are being passed into a function and you have no way of knowing ahead of time whether they're really the same.
The line bool test = s2-s1 does pointer subtraction, giving the number of chars separating s2 from s1. This result is then converted to a bool by converting to false if and only if the result is 0, otherwise converting to true.
For a detailed description of what's going on when you add/subtract pointers, see:
http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/BitOp/pointer.html
C++ allows implicit conversions, so what it is doing is subtracting the pointer values of one array from another and if the result is null, then it is implicitly casting null to false. Anything else will be true, as bools work such that it's either zero (false) or true.
Thanks to Nathan S. and indiv for correcting me.
Related
So, I am making a mid square hashing function as part of a project for school, and I am perplexed how my computer is taking two random string elements out of a string when I am only asking for one element. Here is a tiny example in code below.
string squaredKey = "54756";
int middleDigit = (ceil(stringSquareKey.length()/2));
cout << squaredKey[middleDigit] << endl; // this prints out 7 as expected
string temp = to_string(squaredKey[middleDigit]);
cout << temp << endl; // This prints out 55 for some reason.
I don't know exactly what the problem is, but I think it has something to do with to_string(). Let me know if you would like to see more code.
std::to_string is for converting numbers to strings. And an unfortunate fact of C++ is that char is also a number in its own right, though it's commonly used to represent ASCII values.
What to_string(squaredKey[middleDigit]); is doing is taking the ASCII value '7' (not 7) and converting it to a decimal number, which is 55.
You should use the std::string constructor that accepts a char and a count:
std::string temp(1, squaredKey[middleDigit]);
std::to_string converts a numeric value to std::string, so its input is treated as a numeric value. stringSquareKey.length()/2 gives character value '7', which corresponds - when treated as a numeric value - to ASCII code 55.
So your code is the same as string temp = to_string(55).
This line of code outputs 0:
std::cout << !+2;
I think it should be 35, since '!' has an ASCII code of 33 and adding 2 to it equals 35.
Why is it like that?
Let's quickly analyze what your code !+2 does. The bare exclamation mark is the logical not operator which negates the truth value of its operand. Integers, such as +2 can be converted to boolean, where 0 means false and every non-zero integer true. That means that !+2 is converted to !true. The negation of true is obviously false, so !+2 is converted to false. When you pipe this boolean into std::cout is is converted to integer again, i.e. true turns into 1 and false turns into 0. That is why you std::cout << !+2; prints 0.
What you wanted to do instead (add 2 to the ASCII code of !) can be achieved as well. Therefore you have to tell the compiler that you want the character ! by enclosing it in single quotes. Then the code std::cout << ('!' + 2); will print 35, as expected. I added some extra parentheses to not rely purely on operator precedence.
#include <iostream>
int main() {
std::cout << ('!' + 2) << '\n';
}
Output:
35
Live on Wandbox
If you want to get the ASCII value of exclamation mark, you need to surround it with single quotes like following.
std::cout << '!' + 0;
What you did is negating a value (this value can be either True or False). Making the value (here integer) positive or negative does not matter (here you explicitly specify 2 as positive), because everything other than zero means True. So, if you do the same thing for zero like following, you would get 1 as output.
std::cout << !+0;
From Stroustrup's TC++PL, 3rd Edition, Section 21.3.3:
If we try to read into a variable v and the operation fails, the value of v should be unchanged (it is unchanged if v is one of the types handled by istream or ostream member functions).
The following example appears to contradict the above quote. Based on the above quote, I was expecting the value of v to remain unchanged -- but it gets zeroed. What's the explanation for this apparent contradictory behaviour?
#include <iostream>
#include <sstream>
int main( )
{
std::stringstream ss;
ss << "The quick brown fox.";
int v = 123;
std::cout << "Before: " << v << "\n";
if( ss >> v )
{
std::cout << "Strange -- was successful at reading a word into an int!\n";
}
std::cout << "After: " << v << "\n";
if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n";
return 1;
}
The output I get using x86_64-w64-mingw32-g++.exe (rubenvb-4.7.2-release) 4.7.2 is:
Before: 123
After: 0
state: failbit
Thanks.
From this reference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set (until C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set. (since C++11)
It seems that your compiler is compiling in C++11 mode, which changes the behavior.
The input operator uses the locale facet std::num_get whose get function invokes do_get. For C++11 it's specified to use std::strtoll et. al. type of functions. Before C++11 it apparently used std::scanf style parsing (going by the reference, I don't have access to the C++03 specification) to extract the numbers. The change in behavior is due to this change in parsing the input.
The operator >> is a formatted input operator.
As such is dependent on the locale for how input is read from the stream:
[istream.formatted.arithmetic]
As in the case of the inserters, these extractors depend on the locale’s num_get<> (22.4.2.1) object to perform parsing the input stream data. These extractors behave as formatted input functions (as described in 27.7.2.2.1). After a sentry object is constructed, the conversion occurs as if performed by the following code fragment:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
As we can see above the value is actually set by the numget facet of the locale imbuded onto the stream.
num_get virtual functions [facet.num.get.virtuals]
Stage 3:
The numeric value to be stored can be one of:
zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.
the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.
the most negative representable value or zero for an unsigned integer type, if the field repre- sents a value too large negative to be represented in val. ios_base::failbit is assigned to err.
The definition of stage 3 changed drastically between n2723 -> n2798
Where do I find the current C or C++ standard documents?
num_get virtual functions [facet.num.get.virtuals]
Stage 3: The result of stage 2 processing can be one of:
A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of scanf) to a value of the type of val . This value is stored in val and ios_base::goodbit is stored in err .
The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is assigned to err.
From Stroustrup's TC++PL, 3rd Edition, Section 21.3.3:
If we try to read into a variable v and the operation fails, the value of v should be unchanged (it is unchanged if v is one of the types handled by istream or ostream member functions).
The following example appears to contradict the above quote. Based on the above quote, I was expecting the value of v to remain unchanged -- but it gets zeroed. What's the explanation for this apparent contradictory behaviour?
#include <iostream>
#include <sstream>
int main( )
{
std::stringstream ss;
ss << "The quick brown fox.";
int v = 123;
std::cout << "Before: " << v << "\n";
if( ss >> v )
{
std::cout << "Strange -- was successful at reading a word into an int!\n";
}
std::cout << "After: " << v << "\n";
if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n";
return 1;
}
The output I get using x86_64-w64-mingw32-g++.exe (rubenvb-4.7.2-release) 4.7.2 is:
Before: 123
After: 0
state: failbit
Thanks.
From this reference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set (until C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set. (since C++11)
It seems that your compiler is compiling in C++11 mode, which changes the behavior.
The input operator uses the locale facet std::num_get whose get function invokes do_get. For C++11 it's specified to use std::strtoll et. al. type of functions. Before C++11 it apparently used std::scanf style parsing (going by the reference, I don't have access to the C++03 specification) to extract the numbers. The change in behavior is due to this change in parsing the input.
The operator >> is a formatted input operator.
As such is dependent on the locale for how input is read from the stream:
[istream.formatted.arithmetic]
As in the case of the inserters, these extractors depend on the locale’s num_get<> (22.4.2.1) object to perform parsing the input stream data. These extractors behave as formatted input functions (as described in 27.7.2.2.1). After a sentry object is constructed, the conversion occurs as if performed by the following code fragment:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
As we can see above the value is actually set by the numget facet of the locale imbuded onto the stream.
num_get virtual functions [facet.num.get.virtuals]
Stage 3:
The numeric value to be stored can be one of:
zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.
the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.
the most negative representable value or zero for an unsigned integer type, if the field repre- sents a value too large negative to be represented in val. ios_base::failbit is assigned to err.
The definition of stage 3 changed drastically between n2723 -> n2798
Where do I find the current C or C++ standard documents?
num_get virtual functions [facet.num.get.virtuals]
Stage 3: The result of stage 2 processing can be one of:
A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of scanf) to a value of the type of val . This value is stored in val and ios_base::goodbit is stored in err .
The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is assigned to err.
int a[2][3];
cout << a+1 << " " << a << " " << (a+1) - a << endl;
Output:
0029FAC0 0029FAB4 1
Shouldn't (a+1)-a be 0029FAC0-0029FAB4=12 ?
No, because pointer arithmetic is scaled depending on the thing you're pointing to. In this case, you're pointing to a three-element array of integers, each four bytes long, for a total of twelve bytes. But that's scaled back to one "element" in your arithmetic.
It's the same reason that you get 0029FAC0 rather than 0029FAB5 (0029FAB4 + 1 when it's not scaled) when printing out a+1.
If you change your output line to:
cout << a+1 << " "
<< a << " "
<< (a+1) - a << " "
<< (int)(a+1)-(int)(a) << endl;
you'll see the scaling disappear in the final term because it's no longer a subtraction of pointers:
0xbfaa0ad4 0xbfaa0ac8 1 12
Keep in mind that the a+1 in (int)(a+1) is still scaled since a is still a pointer there. It's only the subtraction that's not scaled because, at that point, both values have been converted to integers (and the usual caveats apply to converting between pointers and integers, it's safe for my particular implementation but C99 doesn't mandate that).
Just as (pointer + N) points to the Nth data element after the pointer argument, going the other way with (pointerA - pointerB) gives you the number of data elements betweeen the pointers. In this case, the data element is int[3] (which you apparently already know since you are expecting 12...).
You shouldn't expect the difference in raw address value (which is machine-dependent in general anyway). C/C++ is converting for you.
Pointer arithmetic is still valid arithmetic ;-)
And as in valid arithmetic, it holds that (x+1)-x = x - x + 1 = 1.
So in your case (a+1) means not pointer to second element of an array, but pointer to the byte after the end of the array.
I would think that the compiler is changing that to a constant.
Try b = a + 1 and then cout << b << b - a << endl;
When you print out a pointer, it's basically implicitly cast to an integer for display, using the byte address.
When you subtract pointers, the result is a ptrdiff_t, which is already an integral type. You can only subtract pointers of the same type, and the sizeof the type is factored into the calculation. The result is the number of elements between the two pointers, not the number of bytes. (Keep in mind that if the two pointers are not pointing into the same array, the subtraction is undefined behaviour.)
In your case, the pointer type is "pointer to array of 3 ints", and your two pointers are to two adjacent elements in an array of 2 of those (array of 3 ints). They are 1 element apart, but 12 bytes apart.
Why would it be 12?
x+1-x=y
y can't possibly be 12, be this pointer arithmetic or integer.